aboutsummaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorLeif Åstrand <leif@vaadin.com>2012-09-05 19:35:55 +0300
committerLeif Åstrand <leif@vaadin.com>2012-09-05 19:35:55 +0300
commitd344148d038498aeb8ef04511d0a44d95ebff32b (patch)
tree1ab0e8fef98bdfe48fa4b7055d8434a16d424fa4 /server
parent4a69dcbca783a0fd0ed353a7a218c31d8d814c34 (diff)
parent4019f7d03a1d8437a24ccadc562c30f99da5efe0 (diff)
downloadvaadin-framework-d344148d038498aeb8ef04511d0a44d95ebff32b.tar.gz
vaadin-framework-d344148d038498aeb8ef04511d0a44d95ebff32b.zip
Merge branch 'removeApplication'
Diffstat (limited to 'server')
-rw-r--r--server/src/com/vaadin/Application.java2308
-rw-r--r--server/src/com/vaadin/DefaultApplicationConfiguration.java229
-rw-r--r--server/src/com/vaadin/data/util/converter/ConverterUtil.java8
-rw-r--r--server/src/com/vaadin/data/util/converter/DefaultConverterFactory.java4
-rw-r--r--server/src/com/vaadin/event/dd/acceptcriteria/SourceIs.java2
-rw-r--r--server/src/com/vaadin/server/AbstractClientConnector.java15
-rw-r--r--server/src/com/vaadin/server/AbstractCommunicationManager.java63
-rw-r--r--server/src/com/vaadin/server/AbstractDeploymentConfiguration.java208
-rw-r--r--server/src/com/vaadin/server/AbstractUIProvider.java91
-rw-r--r--server/src/com/vaadin/server/AddonContext.java9
-rw-r--r--server/src/com/vaadin/server/ApplicationConfiguration.java99
-rw-r--r--server/src/com/vaadin/server/ApplicationContext.java308
-rw-r--r--server/src/com/vaadin/server/ApplicationStartedEvent.java7
-rw-r--r--server/src/com/vaadin/server/ApplicationStartedListener.java5
-rw-r--r--server/src/com/vaadin/server/BootstrapFragmentResponse.java5
-rw-r--r--server/src/com/vaadin/server/BootstrapHandler.java30
-rw-r--r--server/src/com/vaadin/server/BootstrapPageResponse.java5
-rw-r--r--server/src/com/vaadin/server/BootstrapResponse.java7
-rw-r--r--server/src/com/vaadin/server/ClassResource.java3
-rw-r--r--server/src/com/vaadin/server/CombinedRequest.java19
-rw-r--r--server/src/com/vaadin/server/CommunicationManager.java13
-rw-r--r--server/src/com/vaadin/server/ConnectorResourceHandler.java5
-rw-r--r--server/src/com/vaadin/server/DefaultUIProvider.java7
-rw-r--r--server/src/com/vaadin/server/DeploymentConfiguration.java87
-rw-r--r--server/src/com/vaadin/server/FileResource.java3
-rw-r--r--server/src/com/vaadin/server/GAEVaadinServlet.java15
-rw-r--r--server/src/com/vaadin/server/GlobalResourceHandler.java3
-rw-r--r--server/src/com/vaadin/server/HttpServletRequestListener.java64
-rw-r--r--server/src/com/vaadin/server/JsonPaintTarget.java2
-rw-r--r--server/src/com/vaadin/server/LegacyVaadinPortlet.java62
-rw-r--r--server/src/com/vaadin/server/LegacyVaadinServlet.java63
-rw-r--r--server/src/com/vaadin/server/Page.java2
-rw-r--r--server/src/com/vaadin/server/PortletCommunicationManager.java14
-rw-r--r--server/src/com/vaadin/server/PortletRequestListener.java66
-rw-r--r--server/src/com/vaadin/server/RequestHandler.java5
-rw-r--r--server/src/com/vaadin/server/RequestTimer.java2
-rw-r--r--server/src/com/vaadin/server/ResourceReference.java2
-rw-r--r--server/src/com/vaadin/server/RestrictedRenderResponse.java2
-rw-r--r--server/src/com/vaadin/server/ServletApplicationContext.java194
-rw-r--r--server/src/com/vaadin/server/ServletPortletHelper.java45
-rw-r--r--server/src/com/vaadin/server/StreamVariable.java3
-rw-r--r--server/src/com/vaadin/server/SystemMessages.java3
-rw-r--r--server/src/com/vaadin/server/UIProvider.java77
-rw-r--r--server/src/com/vaadin/server/UnsupportedBrowserHandler.java3
-rw-r--r--server/src/com/vaadin/server/VaadinPortlet.java278
-rw-r--r--server/src/com/vaadin/server/VaadinPortletSession.java (renamed from server/src/com/vaadin/server/PortletApplicationContext2.java)205
-rw-r--r--server/src/com/vaadin/server/VaadinServlet.java312
-rw-r--r--server/src/com/vaadin/server/VaadinServletSession.java100
-rw-r--r--server/src/com/vaadin/server/VaadinSession.java1978
-rw-r--r--server/src/com/vaadin/server/WrappedHttpServletRequest.java19
-rw-r--r--server/src/com/vaadin/server/WrappedHttpSession.java66
-rw-r--r--server/src/com/vaadin/server/WrappedPortletRequest.java19
-rw-r--r--server/src/com/vaadin/server/WrappedPortletResponse.java8
-rw-r--r--server/src/com/vaadin/server/WrappedPortletSession.java65
-rw-r--r--server/src/com/vaadin/server/WrappedRequest.java43
-rw-r--r--server/src/com/vaadin/server/WrappedSession.java69
-rw-r--r--server/src/com/vaadin/ui/AbstractComponent.java31
-rw-r--r--server/src/com/vaadin/ui/AbstractField.java2
-rw-r--r--server/src/com/vaadin/ui/Component.java25
-rw-r--r--server/src/com/vaadin/ui/ConnectorTracker.java2
-rw-r--r--server/src/com/vaadin/ui/Label.java2
-rw-r--r--server/src/com/vaadin/ui/LoginForm.java10
-rw-r--r--server/src/com/vaadin/ui/Table.java2
-rw-r--r--server/src/com/vaadin/ui/UI.java83
-rw-r--r--server/src/com/vaadin/util/CurrentInstance.java131
-rw-r--r--server/tests/src/com/vaadin/server/TestAbstractApplicationServletStaticFilesLocation.java4
-rw-r--r--server/tests/src/com/vaadin/tests/VaadinClasses.java4
-rw-r--r--server/tests/src/com/vaadin/tests/data/converter/ConverterFactory.java18
-rw-r--r--server/tests/src/com/vaadin/tests/server/TestMimeTypes.java9
-rw-r--r--server/tests/src/com/vaadin/tests/server/TestStreamVariableMapping.java13
-rw-r--r--server/tests/src/com/vaadin/tests/server/TransactionListenersConcurrency.java201
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/abstractfield/AbstractFieldValueConversions.java8
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/abstractfield/DefaultConverterFactory.java6
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/abstractfield/RemoveListenersOnDetach.java8
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/label/LabelConverters.java4
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/root/CustomUIClassLoader.java36
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/window/AddRemoveSubWindow.java2
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/window/AttachDetachWindow.java51
78 files changed, 3802 insertions, 4179 deletions
diff --git a/server/src/com/vaadin/Application.java b/server/src/com/vaadin/Application.java
index 9498534b4a..13ce23d1e4 100644
--- a/server/src/com/vaadin/Application.java
+++ b/server/src/com/vaadin/Application.java
@@ -16,2267 +16,287 @@
package com.vaadin;
-import java.io.IOException;
-import java.io.Serializable;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Method;
-import java.net.SocketException;
import java.net.URL;
-import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
-import java.util.Enumeration;
-import java.util.EventObject;
import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
-import java.util.Properties;
-import java.util.logging.Level;
-import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import com.vaadin.annotations.PreserveOnRefresh;
-import com.vaadin.annotations.Theme;
-import com.vaadin.annotations.Title;
-import com.vaadin.annotations.Widgetset;
-import com.vaadin.data.util.converter.Converter;
-import com.vaadin.data.util.converter.ConverterFactory;
-import com.vaadin.data.util.converter.DefaultConverterFactory;
-import com.vaadin.event.EventRouter;
-import com.vaadin.server.AbstractErrorMessage;
-import com.vaadin.server.ApplicationContext;
-import com.vaadin.server.BootstrapFragmentResponse;
-import com.vaadin.server.BootstrapListener;
-import com.vaadin.server.BootstrapPageResponse;
-import com.vaadin.server.BootstrapResponse;
-import com.vaadin.server.ChangeVariablesErrorEvent;
-import com.vaadin.server.ClientConnector;
-import com.vaadin.server.CombinedRequest;
-import com.vaadin.server.DeploymentConfiguration;
-import com.vaadin.server.GlobalResourceHandler;
-import com.vaadin.server.RequestHandler;
-import com.vaadin.server.ServletApplicationContext;
-import com.vaadin.server.Terminal;
-import com.vaadin.server.UIProvider;
-import com.vaadin.server.VaadinServlet;
-import com.vaadin.server.VariableOwner;
+import com.vaadin.server.AbstractUIProvider;
+import com.vaadin.server.VaadinSession;
+import com.vaadin.server.Terminal.ErrorEvent;
+import com.vaadin.server.Terminal.ErrorListener;
import com.vaadin.server.WrappedRequest;
-import com.vaadin.server.WrappedRequest.BrowserDetails;
-import com.vaadin.server.WrappedResponse;
-import com.vaadin.shared.ui.ui.UIConstants;
-import com.vaadin.ui.AbstractComponent;
-import com.vaadin.ui.AbstractField;
-import com.vaadin.ui.Table;
import com.vaadin.ui.UI;
-import com.vaadin.ui.Window;
-import com.vaadin.util.ReflectTools;
/**
- * <p>
- * Base class required for all Vaadin applications. This class provides all the
- * basic services required by Vaadin. These services allow external discovery
- * and manipulation of the user, {@link com.vaadin.ui.Window windows} and
- * themes, and starting and stopping the application.
- * </p>
+ * A special application designed to help migrating applications from Vaadin 6
+ * to Vaadin 7. The legacy application supports setting a main window, adding
+ * additional browser level windows and defining the theme for the entire
+ * application.
*
- * <p>
- * As mentioned, all Vaadin applications must inherit this class. However, this
- * is almost all of what one needs to do to create a fully functional
- * application. The only thing a class inheriting the <code>Application</code>
- * needs to do is implement the <code>init</code> method where it creates the
- * windows it needs to perform its function. Note that all applications must
- * have at least one window: the main window. The first unnamed window
- * constructed by an application automatically becomes the main window which
- * behaves just like other windows with one exception: when accessing windows
- * using URLs the main window corresponds to the application URL whereas other
- * windows correspond to a URL gotten by catenating the window's name to the
- * application URL.
- * </p>
+ * @deprecated This class is only intended to ease migration and should not be
+ * used for new projects.
*
- * <p>
- * See the class <code>com.vaadin.demo.HelloWorld</code> for a simple example of
- * a fully working application.
- * </p>
- *
- * <p>
- * <strong>Window access.</strong> <code>Application</code> provides methods to
- * list, add and remove the windows it contains.
- * </p>
- *
- * <p>
- * <strong>Execution control.</strong> This class includes method to start and
- * finish the execution of the application. Being finished means basically that
- * no windows will be available from the application anymore.
- * </p>
- *
- * <p>
- * <strong>Theme selection.</strong> The theme selection process allows a theme
- * to be specified at three different levels. When a window's theme needs to be
- * found out, the window itself is queried for a preferred theme. If the window
- * does not prefer a specific theme, the application containing the window is
- * queried. If neither the application prefers a theme, the default theme for
- * the {@link com.vaadin.server.Terminal terminal} is used. The terminal always
- * defines a default theme.
- * </p>
- *
- * @author Vaadin Ltd.
- * @since 3.0
+ * @since 7.0
*/
-@SuppressWarnings("serial")
-public class Application implements Terminal.ErrorListener, Serializable {
-
+@Deprecated
+public abstract class Application extends AbstractUIProvider implements
+ ErrorListener {
/**
- * 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.
+ * Ignore initial / and then get everything up to the next /
*/
- public static final String UI_PARAMETER = "UI";
-
- private static final Method BOOTSTRAP_FRAGMENT_METHOD = ReflectTools
- .findMethod(BootstrapListener.class, "modifyBootstrapFragment",
- BootstrapFragmentResponse.class);
- private static final Method BOOTSTRAP_PAGE_METHOD = ReflectTools
- .findMethod(BootstrapListener.class, "modifyBootstrapPage",
- BootstrapPageResponse.class);
-
- /**
- * A special application designed to help migrating applications from Vaadin
- * 6 to Vaadin 7. The legacy application supports setting a main window,
- * adding additional browser level windows and defining the theme for the
- * entire application.
- *
- * @deprecated This class is only intended to ease migration and should not
- * be used for new projects.
- *
- * @since 7.0
- */
- @Deprecated
- public static class LegacyApplication extends Application {
- /**
- * Ignore initial / and then get everything up to the next /
- */
- private static final Pattern WINDOW_NAME_PATTERN = Pattern
- .compile("^/?([^/]+).*");
-
- private UI.LegacyWindow mainWindow;
- private String theme;
-
- private Map<String, UI.LegacyWindow> legacyUINames = new HashMap<String, UI.LegacyWindow>();
-
- /**
- * Sets the main window of this application. Setting window as a main
- * window of this application also adds the window to this application.
- *
- * @param mainWindow
- * the UI to set as the default window
- */
- public void setMainWindow(UI.LegacyWindow mainWindow) {
- if (this.mainWindow != null) {
- throw new IllegalStateException(
- "mainWindow has already been set");
- }
- if (mainWindow.getApplication() == null) {
- mainWindow.setApplication(this);
- } else if (mainWindow.getApplication() != this) {
- throw new IllegalStateException(
- "mainWindow is attached to another application");
- }
- if (UI.getCurrent() == null) {
- // Assume setting a main window from Application.init if there's
- // no current UI -> set the main window as the current UI
- UI.setCurrent(mainWindow);
- }
- this.mainWindow = mainWindow;
- }
-
- /**
- * Gets the mainWindow of the application.
- *
- * <p>
- * The main window is the window attached to the application URL (
- * {@link #getURL()}) and thus which is show by default to the user.
- * </p>
- * <p>
- * Note that each application must have at least one main window.
- * </p>
- *
- * @return the UI used as the default window
- */
- public UI.LegacyWindow getMainWindow() {
- 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
- protected <T extends UI> T createUIInstance(WrappedRequest request,
- Class<T> uiClass) {
- return uiClass.cast(getUIInstance(request));
- }
-
- 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 getUIForRequest(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;
- }
- }
-
- /**
- * 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 Class<? extends UI> getUIClass(WrappedRequest request) {
- return getUIInstance(request).getClass();
- }
-
- /**
- * Sets the application's theme.
- * <p>
- * Note that this theme can be overridden for a specific UI with
- * {@link Application#getThemeForUI(UI)}. Setting theme to be
- * <code>null</code> selects the default theme. For the available theme
- * names, see the contents of the VAADIN/themes directory.
- * </p>
- *
- * @param theme
- * the new theme for this application.
- */
- public void setTheme(String theme) {
- this.theme = theme;
- }
-
- /**
- * Gets the application's theme. The application's theme is the default
- * theme used by all the uIs for which a theme is not explicitly
- * defined. If the application theme is not explicitly set,
- * <code>null</code> is returned.
- *
- * @return the name of the application's theme.
- */
- public String getTheme() {
- return theme;
- }
-
- /**
- * This implementation returns the theme that has been set using
- * {@link #setTheme(String)}
- * <p>
- * {@inheritDoc}
- */
- @Override
- public String getThemeForUI(WrappedRequest request,
- Class<? extends UI> uiClass) {
- return theme;
- }
+ private static final Pattern WINDOW_NAME_PATTERN = Pattern
+ .compile("^/?([^/]+).*");
- /**
- * <p>
- * Gets a UI by name. Returns <code>null</code> if the application is
- * not running or it does not contain a window corresponding to the
- * name.
- * </p>
- *
- * @param name
- * the name of the requested window
- * @return a UI corresponding to the name, or <code>null</code> to use
- * the default window
- */
- public UI.LegacyWindow getWindow(String name) {
- return legacyUINames.get(name);
- }
-
- /**
- * Counter to get unique names for windows with no explicit name
- */
- private int namelessUIIndex = 0;
-
- /**
- * Adds a new browser level window to this application. Please note that
- * UI doesn't have a name that is used in the URL - to add a named
- * window you should instead use {@link #addWindow(UI, String)}
- *
- * @param uI
- * the UI window to add to the application
- * @return returns the name that has been assigned to the window
- *
- * @see #addWindow(UI, String)
- */
- public void addWindow(UI.LegacyWindow uI) {
- if (uI.getName() == null) {
- String name = Integer.toString(namelessUIIndex++);
- uI.setName(name);
- }
-
- legacyUINames.put(uI.getName(), uI);
- uI.setApplication(this);
- }
+ private UI.LegacyWindow mainWindow;
+ private String theme;
- /**
- * Removes the specified window from the application. This also removes
- * all name mappings for the window (see {@link #addWindow(UI, String)
- * and #getWindowName(UI)}.
- *
- * <p>
- * Note that removing window from the application does not close the
- * browser window - the window is only removed from the server-side.
- * </p>
- *
- * @param uI
- * the UI to remove
- */
- public void removeWindow(UI.LegacyWindow uI) {
- for (Entry<String, UI.LegacyWindow> entry : legacyUINames
- .entrySet()) {
- if (entry.getValue() == uI) {
- legacyUINames.remove(entry.getKey());
- }
- }
- }
-
- /**
- * Gets the set of windows contained by the application.
- *
- * <p>
- * Note that the returned set of windows can not be modified.
- * </p>
- *
- * @return the unmodifiable collection of windows.
- */
- public Collection<UI.LegacyWindow> getWindows() {
- return Collections.unmodifiableCollection(legacyUINames.values());
- }
- }
+ private Map<String, UI.LegacyWindow> legacyUINames = new HashMap<String, UI.LegacyWindow>();
/**
- * An event sent to {@link #start(ApplicationStartEvent)} when a new
- * Application is being started.
+ * Sets the main window of this application. Setting window as a main window
+ * of this application also adds the window to this application.
*
- * @since 7.0
+ * @param mainWindow
+ * the UI to set as the default window
*/
- public static class ApplicationStartEvent implements Serializable {
- private final URL applicationUrl;
-
- private final DeploymentConfiguration configuration;
-
- private final ApplicationContext context;
-
- /**
- * @param applicationUrl
- * the URL the application should respond to.
- * @param configuration
- * the deployment configuration for the application.
- * @param context
- * the context application will be running in.
- */
- public ApplicationStartEvent(URL applicationUrl,
- DeploymentConfiguration configuration,
- ApplicationContext context) {
- this.applicationUrl = applicationUrl;
- this.configuration = configuration;
- this.context = context;
+ public void setMainWindow(UI.LegacyWindow mainWindow) {
+ if (this.mainWindow != null) {
+ throw new IllegalStateException("mainWindow has already been set");
}
-
- /**
- * Gets the URL the application should respond to.
- *
- * @return the URL the application should respond to or
- * <code>null</code> if the URL is not defined.
- *
- * @see Application#getURL()
- */
- public URL getApplicationUrl() {
- return applicationUrl;
- }
-
- /**
- * Returns the deployment configuration used by this application.
- *
- * @return the deployment configuration.
- */
- public DeploymentConfiguration getConfiguration() {
- return configuration;
- }
-
- /**
- * Gets the context application will be running in.
- *
- * @return the context application will be running in.
- *
- * @see Application#getContext()
- */
- public ApplicationContext getContext() {
- return context;
+ if (mainWindow.getSession() == null) {
+ mainWindow.setSession(VaadinSession.getCurrent());
+ } else if (mainWindow.getSession() != VaadinSession.getCurrent()) {
+ throw new IllegalStateException(
+ "mainWindow is attached to another application");
}
- }
-
- private final static Logger logger = Logger.getLogger(Application.class
- .getName());
-
- /**
- * Application context the application is running in.
- */
- private ApplicationContext context;
-
- /**
- * Deployment configuration for the application.
- */
- private DeploymentConfiguration configuration;
-
- /**
- * The application's URL.
- */
- private URL applicationUrl;
-
- /**
- * Application status.
- */
- private volatile boolean applicationIsRunning = false;
-
- /**
- * Default locale of the application.
- */
- 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;
-
- /**
- * Application wide error handler which is used by default if an error is
- * left unhandled.
- */
- private Terminal.ErrorListener errorHandler = this;
-
- /**
- * The converter factory that is used to provide default converters for the
- * application.
- */
- private ConverterFactory converterFactory = new DefaultConverterFactory();
-
- private LinkedList<RequestHandler> requestHandlers = new LinkedList<RequestHandler>();
-
- private int nextUIId = 0;
- private Map<Integer, UI> uIs = new HashMap<Integer, UI>();
-
- private final Map<String, Integer> retainOnRefreshUIs = new HashMap<String, Integer>();
-
- private final EventRouter eventRouter = new EventRouter();
-
- private List<UIProvider> uiProviders = new LinkedList<UIProvider>();
-
- private GlobalResourceHandler globalResourceHandler;
-
- /**
- * Gets the URL of the application.
- *
- * <p>
- * This is the URL what can be entered to a browser window to start the
- * application. Navigating to the application URL shows the main window (
- * {@link #getMainWindow()}) of the application. Note that the main window
- * can also be shown by navigating to the window url (
- * {@link com.vaadin.ui.Window#getURL()}).
- * </p>
- *
- * @return the application's URL.
- */
- public URL getURL() {
- return applicationUrl;
- }
-
- /**
- * Ends the Application.
- * <p>
- * In effect this will cause the application stop returning any windows when
- * asked. When the application is closed, close events are fired for its
- * UIs, its state is removed from the 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.
- */
- public void close() {
- applicationIsRunning = false;
- for (UI ui : getUIs()) {
- ui.fireCloseEvent();
+ if (UI.getCurrent() == null) {
+ // Assume setting a main window from Application.init if there's
+ // no current UI -> set the main window as the current UI
+ UI.setCurrent(mainWindow);
}
+ this.mainWindow = mainWindow;
}
- /**
- * Starts the application on the given URL.
- *
- * <p>
- * This method is called by Vaadin framework when a user navigates to the
- * application. After this call the application corresponds to the given URL
- * and it will return windows when asked for them. There is no need to call
- * this method directly.
- * </p>
- *
- * <p>
- * Application properties are defined by servlet configuration object
- * {@link javax.servlet.ServletConfig} and they are overridden by
- * context-wide initialization parameters
- * {@link javax.servlet.ServletContext}.
- * </p>
- *
- * @param event
- * the application start event containing details required for
- * starting the application.
- *
- */
- public void start(ApplicationStartEvent event) {
- applicationUrl = event.getApplicationUrl();
- configuration = event.getConfiguration();
- context = event.getContext();
+ public void doInit() {
+ VaadinSession.getCurrent().setErrorHandler(this);
init();
- applicationIsRunning = true;
- }
-
- /**
- * Tests if the application is running or if it has been finished.
- *
- * <p>
- * Application starts running when its
- * {@link #start(URL, Properties, ApplicationContext)} 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.
- */
- public boolean isRunning() {
- return applicationIsRunning;
- }
-
- /**
- * <p>
- * Main initializer of the application. The <code>init</code> method is
- * called by the framework when the application is started, and it should
- * perform whatever initialization operations the application needs.
- * </p>
- */
- public void init() {
- // Default implementation does nothing
- }
-
- /**
- * Returns the properties of this application as specified in the deployment
- * configuration.
- *
- * @return Application properties
- */
- protected Properties getProperties() {
- return configuration.getInitParameters();
- }
-
- /**
- * Returns an enumeration of all the names in this application.
- *
- * <p>
- * See {@link #start(URL, Properties, ApplicationContext)} how properties
- * are defined.
- * </p>
- *
- * @return an enumeration of all the keys in this property list, including
- * the keys in the default property list.
- *
- */
- public Enumeration<?> getPropertyNames() {
- return getProperties().propertyNames();
- }
-
- /**
- * Searches for the property with the specified name in this application.
- * This method returns <code>null</code> if the property is not found.
- *
- * See {@link #start(URL, Properties, ApplicationContext)} how properties
- * are defined.
- *
- * @param name
- * the name of the property.
- * @return the value in this property list with the specified key value.
- */
- public String getProperty(String name) {
- return getProperties().getProperty(name);
- }
-
- /**
- * Gets the default locale for this application.
- *
- * By default this is the preferred locale of the user using the
- * application. In most cases it is read from the browser defaults.
- *
- * @return the locale of this application.
- */
- public Locale getLocale() {
- if (locale != null) {
- return locale;
- }
- return Locale.getDefault();
}
- /**
- * Sets the default locale for this application.
- *
- * By default this is the preferred locale of the user using the
- * application. In most cases it is read from the browser defaults.
- *
- * @param locale
- * the Locale object.
- *
- */
- public void setLocale(Locale locale) {
- this.locale = locale;
- }
-
- /**
- * Window detach event.
- *
- * This event is sent each time a window is removed from the application
- * with {@link com.vaadin.Application#removeWindow(Window)}.
- */
- public static class WindowDetachEvent extends EventObject {
-
- private final Window window;
-
- /**
- * Creates a event.
- *
- * @param application
- * the application to which the detached window belonged.
- * @param window
- * the Detached window.
- */
- public WindowDetachEvent(Application application, Window window) {
- super(application);
- this.window = window;
- }
+ protected abstract void init();
- /**
- * Gets the detached window.
- *
- * @return the detached window.
- */
- public Window getWindow() {
- return window;
- }
-
- /**
- * Gets the application from which the window was detached.
- *
- * @return the Application.
- */
- public Application getApplication() {
- return (Application) getSource();
- }
- }
-
- /**
- * Window attach event.
- *
- * This event is sent each time a window is attached tothe application with
- * {@link com.vaadin.Application#addWindow(Window)}.
- */
- public static class WindowAttachEvent extends EventObject {
-
- private final Window window;
-
- /**
- * Creates a event.
- *
- * @param application
- * the application to which the detached window belonged.
- * @param window
- * the Attached window.
- */
- public WindowAttachEvent(Application application, Window window) {
- super(application);
- this.window = window;
- }
-
- /**
- * Gets the attached window.
- *
- * @return the attached window.
- */
- public Window getWindow() {
- return window;
- }
-
- /**
- * Gets the application to which the window was attached.
- *
- * @return the Application.
- */
- public Application getApplication() {
- return (Application) getSource();
+ @Override
+ public Class<? extends UI> getUIClass(VaadinSession application,
+ WrappedRequest request) {
+ UI uiInstance = getUIInstance(request);
+ if (uiInstance != null) {
+ return uiInstance.getClass();
}
+ return null;
}
- /**
- * Window attach listener interface.
- */
- public interface WindowAttachListener extends Serializable {
-
- /**
- * Window attached
- *
- * @param event
- * the window attach event.
- */
- public void windowAttached(WindowAttachEvent event);
- }
-
- /**
- * Window detach listener interface.
- */
- public interface WindowDetachListener extends Serializable {
-
- /**
- * Window detached.
- *
- * @param event
- * the window detach event.
- */
- 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.
- */
- public String getLogoutURL() {
- return logoutURL;
+ @Override
+ public UI createInstance(VaadinSession application, Class<? extends UI> type,
+ WrappedRequest request) {
+ return getUIInstance(request);
}
- /**
- * 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.
- */
- public void setLogoutURL(String logoutURL) {
- this.logoutURL = logoutURL;
+ @Override
+ public String getThemeForUI(WrappedRequest request,
+ Class<? extends UI> uiClass) {
+ return theme;
}
- /**
- * <p>
- * Invoked by the terminal on any exception that occurs in application and
- * is thrown by the <code>setVariable</code> to the terminal. The default
- * implementation sets the exceptions as <code>ComponentErrors</code> to the
- * component that initiated the exception and prints stack trace to standard
- * error stream.
- * </p>
- * <p>
- * You can safely override this method in your application in order to
- * direct the errors to some other destination (for example log).
- * </p>
- *
- * @param event
- * the change event.
- * @see com.vaadin.server.Terminal.ErrorListener#terminalError(com.vaadin.server.Terminal.ErrorEvent)
- */
-
@Override
- public void terminalError(Terminal.ErrorEvent event) {
- final Throwable t = event.getThrowable();
- if (t instanceof SocketException) {
- // Most likely client browser closed socket
- getLogger().info(
- "SocketException in CommunicationManager."
- + " Most likely client (browser) closed socket.");
- return;
- }
-
- // Finds the original source of the error/exception
- Object owner = null;
- if (event instanceof VariableOwner.ErrorEvent) {
- owner = ((VariableOwner.ErrorEvent) event).getVariableOwner();
- } else if (event instanceof ChangeVariablesErrorEvent) {
- owner = ((ChangeVariablesErrorEvent) event).getComponent();
- }
-
- // Shows the error in AbstractComponent
- if (owner instanceof AbstractComponent) {
- ((AbstractComponent) owner).setComponentError(AbstractErrorMessage
- .getErrorMessageForException(t));
+ 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);
}
-
- // also print the error on console
- getLogger().log(Level.SEVERE, "Terminal error:", t);
- }
-
- /**
- * Gets the application context.
- * <p>
- * The application context is the environment where the application is
- * running in. The actual implementation class of may contains quite a lot
- * more functionality than defined in the {@link ApplicationContext}
- * interface.
- * </p>
- * <p>
- * By default, when you are deploying your application to a servlet
- * container, the implementation class is {@link ServletApplicationContext}
- * - you can safely cast to this class and use the methods from there. When
- * you are deploying your application as a portlet, context implementation
- * is {@link PortletApplicationContext}.
- * </p>
- *
- * @return the application context.
- */
- public ApplicationContext getContext() {
- return context;
}
/**
- * Gets the application error handler.
+ * Gets the mainWindow of the application.
*
- * The default error handler is the application itself.
- *
- * @return Application error handler
- */
- public Terminal.ErrorListener getErrorHandler() {
- return errorHandler;
- }
-
- /**
- * Sets the application error handler.
- *
- * The default error handler is the application itself. By overriding this,
- * you can redirect the error messages to your selected target (log for
- * example).
- *
- * @param errorHandler
- */
- public void setErrorHandler(Terminal.ErrorListener errorHandler) {
- this.errorHandler = errorHandler;
- }
-
- /**
- * Gets the {@link ConverterFactory} used to locate a suitable
- * {@link Converter} for fields in the application.
- *
- * See {@link #setConverterFactory(ConverterFactory)} for more details
- *
- * @return The converter factory used in the application
- */
- public ConverterFactory getConverterFactory() {
- return converterFactory;
- }
-
- /**
- * Sets the {@link ConverterFactory} used to locate a suitable
- * {@link Converter} for fields in the application.
* <p>
- * The {@link ConverterFactory} is used to find a suitable converter when
- * binding data to a UI component and the data type does not match the UI
- * component type, e.g. binding a Double to a TextField (which is based on a
- * String).
+ * The main window is the window attached to the application URL (
+ * {@link #getURL()}) and thus which is show by default to the user.
* </p>
* <p>
- * The {@link Converter} for an individual field can be overridden using
- * {@link AbstractField#setConverter(Converter)} and for individual property
- * ids in a {@link Table} using
- * {@link Table#setConverter(Object, Converter)}.
+ * Note that each application must have at least one main window.
* </p>
- * <p>
- * The converter factory must never be set to null.
*
- * @param converterFactory
- * The converter factory used in the application
+ * @return the UI used as the default window
*/
- public void setConverterFactory(ConverterFactory converterFactory) {
- this.converterFactory = converterFactory;
+ public UI.LegacyWindow getMainWindow() {
+ return mainWindow;
}
- /**
- * Contains the system messages used to notify the user about various
- * critical situations that can occur.
- * <p>
- * Customize by overriding the static
- * {@link Application#getSystemMessages()} and returning
- * {@link CustomizedSystemMessages}.
- * </p>
- * <p>
- * The defaults defined in this class are:
- * <ul>
- * <li><b>sessionExpiredURL</b> = null</li>
- * <li><b>sessionExpiredNotificationEnabled</b> = true</li>
- * <li><b>sessionExpiredCaption</b> = ""</li>
- * <li><b>sessionExpiredMessage</b> =
- * "Take note of any unsaved data, and <u>click here</u> to continue."</li>
- * <li><b>communicationErrorURL</b> = null</li>
- * <li><b>communicationErrorNotificationEnabled</b> = true</li>
- * <li><b>communicationErrorCaption</b> = "Communication problem"</li>
- * <li><b>communicationErrorMessage</b> =
- * "Take note of any unsaved data, and <u>click here</u> to continue."</li>
- * <li><b>internalErrorURL</b> = null</li>
- * <li><b>internalErrorNotificationEnabled</b> = true</li>
- * <li><b>internalErrorCaption</b> = "Internal error"</li>
- * <li><b>internalErrorMessage</b> = "Please notify the administrator.<br/>
- * Take note of any unsaved data, and <u>click here</u> to continue."</li>
- * <li><b>outOfSyncURL</b> = null</li>
- * <li><b>outOfSyncNotificationEnabled</b> = true</li>
- * <li><b>outOfSyncCaption</b> = "Out of sync"</li>
- * <li><b>outOfSyncMessage</b> = "Something has caused us to be out of sync
- * with the server.<br/>
- * Take note of any unsaved data, and <u>click here</u> to re-sync."</li>
- * <li><b>cookiesDisabledURL</b> = null</li>
- * <li><b>cookiesDisabledNotificationEnabled</b> = true</li>
- * <li><b>cookiesDisabledCaption</b> = "Cookies disabled"</li>
- * <li><b>cookiesDisabledMessage</b> = "This application requires cookies to
- * function.<br/>
- * Please enable cookies in your browser and <u>click here</u> to try again.
- * </li>
- * </ul>
- * </p>
- *
- */
- public static class SystemMessages implements Serializable {
- protected String sessionExpiredURL = null;
- protected boolean sessionExpiredNotificationEnabled = true;
- protected String sessionExpiredCaption = "Session Expired";
- protected String sessionExpiredMessage = "Take note of any unsaved data, and <u>click here</u> to continue.";
-
- protected String communicationErrorURL = null;
- protected boolean communicationErrorNotificationEnabled = true;
- protected String communicationErrorCaption = "Communication problem";
- protected String communicationErrorMessage = "Take note of any unsaved data, and <u>click here</u> to continue.";
-
- protected String authenticationErrorURL = null;
- protected boolean authenticationErrorNotificationEnabled = true;
- protected String authenticationErrorCaption = "Authentication problem";
- protected String authenticationErrorMessage = "Take note of any unsaved data, and <u>click here</u> to continue.";
-
- protected String internalErrorURL = null;
- protected boolean internalErrorNotificationEnabled = true;
- protected String internalErrorCaption = "Internal error";
- protected String internalErrorMessage = "Please notify the administrator.<br/>Take note of any unsaved data, and <u>click here</u> to continue.";
-
- protected String outOfSyncURL = null;
- protected boolean outOfSyncNotificationEnabled = true;
- protected String outOfSyncCaption = "Out of sync";
- protected String outOfSyncMessage = "Something has caused us to be out of sync with the server.<br/>Take note of any unsaved data, and <u>click here</u> to re-sync.";
-
- protected String cookiesDisabledURL = null;
- protected boolean cookiesDisabledNotificationEnabled = true;
- protected String cookiesDisabledCaption = "Cookies disabled";
- protected String cookiesDisabledMessage = "This application requires cookies to function.<br/>Please enable cookies in your browser and <u>click here</u> to try again.";
-
- /**
- * Use {@link CustomizedSystemMessages} to customize
- */
- private SystemMessages() {
-
- }
-
- /**
- * @return null to indicate that the application will be restarted after
- * session expired message has been shown.
- */
- public String getSessionExpiredURL() {
- return sessionExpiredURL;
- }
-
- /**
- * @return true to show session expiration message.
- */
- public boolean isSessionExpiredNotificationEnabled() {
- return sessionExpiredNotificationEnabled;
- }
-
- /**
- * @return "" to show no caption.
- */
- public String getSessionExpiredCaption() {
- return (sessionExpiredNotificationEnabled ? sessionExpiredCaption
- : null);
- }
-
- /**
- * @return
- * "Take note of any unsaved data, and <u>click here</u> to continue."
- */
- public String getSessionExpiredMessage() {
- return (sessionExpiredNotificationEnabled ? sessionExpiredMessage
- : null);
- }
-
- /**
- * @return null to reload the application after communication error
- * message.
- */
- public String getCommunicationErrorURL() {
- return communicationErrorURL;
- }
-
- /**
- * @return true to show the communication error message.
- */
- public boolean isCommunicationErrorNotificationEnabled() {
- return communicationErrorNotificationEnabled;
- }
-
- /**
- * @return "Communication problem"
- */
- public String getCommunicationErrorCaption() {
- return (communicationErrorNotificationEnabled ? communicationErrorCaption
- : null);
- }
-
- /**
- * @return
- * "Take note of any unsaved data, and <u>click here</u> to continue."
- */
- public String getCommunicationErrorMessage() {
- return (communicationErrorNotificationEnabled ? communicationErrorMessage
- : null);
- }
-
- /**
- * @return null to reload the application after authentication error
- * message.
- */
- public String getAuthenticationErrorURL() {
- return authenticationErrorURL;
- }
-
- /**
- * @return true to show the authentication error message.
- */
- public boolean isAuthenticationErrorNotificationEnabled() {
- return authenticationErrorNotificationEnabled;
- }
-
- /**
- * @return "Authentication problem"
- */
- public String getAuthenticationErrorCaption() {
- return (authenticationErrorNotificationEnabled ? authenticationErrorCaption
- : null);
- }
-
- /**
- * @return
- * "Take note of any unsaved data, and <u>click here</u> to continue."
- */
- public String getAuthenticationErrorMessage() {
- return (authenticationErrorNotificationEnabled ? authenticationErrorMessage
- : null);
- }
-
- /**
- * @return null to reload the current URL after internal error message
- * has been shown.
- */
- public String getInternalErrorURL() {
- return internalErrorURL;
- }
-
- /**
- * @return true to enable showing of internal error message.
- */
- public boolean isInternalErrorNotificationEnabled() {
- return internalErrorNotificationEnabled;
- }
-
- /**
- * @return "Internal error"
- */
- public String getInternalErrorCaption() {
- return (internalErrorNotificationEnabled ? internalErrorCaption
- : null);
- }
-
- /**
- * @return "Please notify the administrator.<br/>
- * Take note of any unsaved data, and <u>click here</u> to
- * continue."
- */
- public String getInternalErrorMessage() {
- return (internalErrorNotificationEnabled ? internalErrorMessage
- : null);
- }
-
- /**
- * @return null to reload the application after out of sync message.
- */
- public String getOutOfSyncURL() {
- return outOfSyncURL;
- }
-
- /**
- * @return true to enable showing out of sync message
- */
- public boolean isOutOfSyncNotificationEnabled() {
- return outOfSyncNotificationEnabled;
- }
-
- /**
- * @return "Out of sync"
- */
- public String getOutOfSyncCaption() {
- return (outOfSyncNotificationEnabled ? outOfSyncCaption : null);
- }
-
- /**
- * @return "Something has caused us to be out of sync with the server.<br/>
- * Take note of any unsaved data, and <u>click here</u> to
- * re-sync."
- */
- public String getOutOfSyncMessage() {
- return (outOfSyncNotificationEnabled ? outOfSyncMessage : null);
- }
-
- /**
- * Returns the URL the user should be redirected to after dismissing the
- * "you have to enable your cookies" message. Typically null.
- *
- * @return A URL the user should be redirected to after dismissing the
- * message or null to reload the current URL.
- */
- public String getCookiesDisabledURL() {
- return cookiesDisabledURL;
- }
-
- /**
- * Determines if "cookies disabled" messages should be shown to the end
- * user or not. If the notification is disabled the user will be
- * immediately redirected to the URL returned by
- * {@link #getCookiesDisabledURL()}.
- *
- * @return true to show "cookies disabled" messages to the end user,
- * false to redirect to the given URL directly
- */
- public boolean isCookiesDisabledNotificationEnabled() {
- return cookiesDisabledNotificationEnabled;
- }
-
- /**
- * Returns the caption of the message shown to the user when cookies are
- * disabled in the browser.
- *
- * @return The caption of the "cookies disabled" message
- */
- public String getCookiesDisabledCaption() {
- return (cookiesDisabledNotificationEnabled ? cookiesDisabledCaption
- : null);
- }
-
- /**
- * Returns the message shown to the user when cookies are disabled in
- * the browser.
- *
- * @return The "cookies disabled" message
- */
- public String getCookiesDisabledMessage() {
- return (cookiesDisabledNotificationEnabled ? cookiesDisabledMessage
- : null);
- }
-
- }
-
- /**
- * Contains the system messages used to notify the user about various
- * critical situations that can occur.
- * <p>
- * Vaadin gets the SystemMessages from your application by calling a static
- * getSystemMessages() method. By default the
- * Application.getSystemMessages() is used. You can customize this by
- * defining a static MyApplication.getSystemMessages() and returning
- * CustomizedSystemMessages. Note that getSystemMessages() is static -
- * changing the system messages will by default change the message for all
- * users of the application.
- * </p>
- * <p>
- * The default behavior is to show a notification, and restart the
- * application the the user clicks the message. <br/>
- * Instead of restarting the application, you can set a specific URL that
- * the user is taken to.<br/>
- * Setting both caption and message to null will restart the application (or
- * go to the specified URL) without displaying a notification.
- * set*NotificationEnabled(false) will achieve the same thing.
- * </p>
- * <p>
- * The situations are:
- * <li>Session expired: the user session has expired, usually due to
- * inactivity.</li>
- * <li>Communication error: the client failed to contact the server, or the
- * server returned and invalid response.</li>
- * <li>Internal error: unhandled critical server error (e.g out of memory,
- * database crash)
- * <li>Out of sync: the client is not in sync with the server. E.g the user
- * opens two windows showing the same application, but the application does
- * not support this and uses the same Window instance. When the user makes
- * changes in one of the windows - the other window is no longer in sync,
- * and (for instance) pressing a button that is no longer present in the UI
- * will cause a out-of-sync -situation.
- * </p>
- */
-
- public static class CustomizedSystemMessages extends SystemMessages
- implements Serializable {
-
- /**
- * Sets the URL to go to when the session has expired.
- *
- * @param sessionExpiredURL
- * the URL to go to, or null to reload current
- */
- public void setSessionExpiredURL(String sessionExpiredURL) {
- this.sessionExpiredURL = sessionExpiredURL;
- }
-
- /**
- * Enables or disables the notification. If disabled, the set URL (or
- * current) is loaded directly when next transaction between server and
- * client happens.
- *
- * @param sessionExpiredNotificationEnabled
- * true = enabled, false = disabled
- */
- public void setSessionExpiredNotificationEnabled(
- boolean sessionExpiredNotificationEnabled) {
- this.sessionExpiredNotificationEnabled = sessionExpiredNotificationEnabled;
- }
-
- /**
- * Sets the caption of the notification. Set to null for no caption. If
- * both caption and message are null, client automatically forwards to
- * sessionExpiredUrl after timeout timer expires. Timer uses value read
- * from HTTPSession.getMaxInactiveInterval()
- *
- * @param sessionExpiredCaption
- * the caption
- */
- public void setSessionExpiredCaption(String sessionExpiredCaption) {
- this.sessionExpiredCaption = sessionExpiredCaption;
- }
-
- /**
- * Sets the message of the notification. Set to null for no message. If
- * both caption and message are null, client automatically forwards to
- * sessionExpiredUrl after timeout timer expires. Timer uses value read
- * from HTTPSession.getMaxInactiveInterval()
- *
- * @param sessionExpiredMessage
- * the message
- */
- public void setSessionExpiredMessage(String sessionExpiredMessage) {
- this.sessionExpiredMessage = sessionExpiredMessage;
- }
-
- /**
- * Sets the URL to go to when there is a authentication error.
- *
- * @param authenticationErrorURL
- * the URL to go to, or null to reload current
- */
- public void setAuthenticationErrorURL(String authenticationErrorURL) {
- this.authenticationErrorURL = authenticationErrorURL;
- }
-
- /**
- * Enables or disables the notification. If disabled, the set URL (or
- * current) is loaded directly.
- *
- * @param authenticationErrorNotificationEnabled
- * true = enabled, false = disabled
- */
- public void setAuthenticationErrorNotificationEnabled(
- boolean authenticationErrorNotificationEnabled) {
- this.authenticationErrorNotificationEnabled = authenticationErrorNotificationEnabled;
- }
-
- /**
- * Sets the caption of the notification. Set to null for no caption. If
- * both caption and message is null, the notification is disabled;
- *
- * @param authenticationErrorCaption
- * the caption
- */
- public void setAuthenticationErrorCaption(
- String authenticationErrorCaption) {
- this.authenticationErrorCaption = authenticationErrorCaption;
- }
-
- /**
- * Sets the message of the notification. Set to null for no message. If
- * both caption and message is null, the notification is disabled;
- *
- * @param authenticationErrorMessage
- * the message
- */
- public void setAuthenticationErrorMessage(
- String authenticationErrorMessage) {
- this.authenticationErrorMessage = authenticationErrorMessage;
- }
-
- /**
- * Sets the URL to go to when there is a communication error.
- *
- * @param communicationErrorURL
- * the URL to go to, or null to reload current
- */
- public void setCommunicationErrorURL(String communicationErrorURL) {
- this.communicationErrorURL = communicationErrorURL;
- }
-
- /**
- * Enables or disables the notification. If disabled, the set URL (or
- * current) is loaded directly.
- *
- * @param communicationErrorNotificationEnabled
- * true = enabled, false = disabled
- */
- public void setCommunicationErrorNotificationEnabled(
- boolean communicationErrorNotificationEnabled) {
- this.communicationErrorNotificationEnabled = communicationErrorNotificationEnabled;
- }
-
- /**
- * Sets the caption of the notification. Set to null for no caption. If
- * both caption and message is null, the notification is disabled;
- *
- * @param communicationErrorCaption
- * the caption
- */
- public void setCommunicationErrorCaption(
- String communicationErrorCaption) {
- this.communicationErrorCaption = communicationErrorCaption;
- }
-
- /**
- * Sets the message of the notification. Set to null for no message. If
- * both caption and message is null, the notification is disabled;
- *
- * @param communicationErrorMessage
- * the message
- */
- public void setCommunicationErrorMessage(
- String communicationErrorMessage) {
- this.communicationErrorMessage = communicationErrorMessage;
- }
-
- /**
- * Sets the URL to go to when an internal error occurs.
- *
- * @param internalErrorURL
- * the URL to go to, or null to reload current
- */
- public void setInternalErrorURL(String internalErrorURL) {
- this.internalErrorURL = internalErrorURL;
- }
-
- /**
- * Enables or disables the notification. If disabled, the set URL (or
- * current) is loaded directly.
- *
- * @param internalErrorNotificationEnabled
- * true = enabled, false = disabled
- */
- public void setInternalErrorNotificationEnabled(
- boolean internalErrorNotificationEnabled) {
- this.internalErrorNotificationEnabled = internalErrorNotificationEnabled;
- }
-
- /**
- * Sets the caption of the notification. Set to null for no caption. If
- * both caption and message is null, the notification is disabled;
- *
- * @param internalErrorCaption
- * the caption
- */
- public void setInternalErrorCaption(String internalErrorCaption) {
- this.internalErrorCaption = internalErrorCaption;
- }
-
- /**
- * Sets the message of the notification. Set to null for no message. If
- * both caption and message is null, the notification is disabled;
- *
- * @param internalErrorMessage
- * the message
- */
- public void setInternalErrorMessage(String internalErrorMessage) {
- this.internalErrorMessage = internalErrorMessage;
- }
-
- /**
- * Sets the URL to go to when the client is out-of-sync.
- *
- * @param outOfSyncURL
- * the URL to go to, or null to reload current
- */
- public void setOutOfSyncURL(String outOfSyncURL) {
- this.outOfSyncURL = outOfSyncURL;
- }
-
- /**
- * Enables or disables the notification. If disabled, the set URL (or
- * current) is loaded directly.
- *
- * @param outOfSyncNotificationEnabled
- * true = enabled, false = disabled
- */
- public void setOutOfSyncNotificationEnabled(
- boolean outOfSyncNotificationEnabled) {
- this.outOfSyncNotificationEnabled = outOfSyncNotificationEnabled;
- }
-
- /**
- * Sets the caption of the notification. Set to null for no caption. If
- * both caption and message is null, the notification is disabled;
- *
- * @param outOfSyncCaption
- * the caption
- */
- public void setOutOfSyncCaption(String outOfSyncCaption) {
- this.outOfSyncCaption = outOfSyncCaption;
- }
-
- /**
- * Sets the message of the notification. Set to null for no message. If
- * both caption and message is null, the notification is disabled;
- *
- * @param outOfSyncMessage
- * the message
- */
- public void setOutOfSyncMessage(String outOfSyncMessage) {
- this.outOfSyncMessage = outOfSyncMessage;
- }
-
- /**
- * Sets the URL to redirect to when the browser has cookies disabled.
- *
- * @param cookiesDisabledURL
- * the URL to redirect to, or null to reload the current URL
- */
- public void setCookiesDisabledURL(String cookiesDisabledURL) {
- this.cookiesDisabledURL = cookiesDisabledURL;
- }
-
- /**
- * Enables or disables the notification for "cookies disabled" messages.
- * If disabled, the URL returned by {@link #getCookiesDisabledURL()} is
- * loaded directly.
- *
- * @param cookiesDisabledNotificationEnabled
- * true to enable "cookies disabled" messages, false
- * otherwise
- */
- public void setCookiesDisabledNotificationEnabled(
- boolean cookiesDisabledNotificationEnabled) {
- this.cookiesDisabledNotificationEnabled = cookiesDisabledNotificationEnabled;
- }
-
- /**
- * Sets the caption of the "cookies disabled" notification. Set to null
- * for no caption. If both caption and message is null, the notification
- * is disabled.
- *
- * @param cookiesDisabledCaption
- * the caption for the "cookies disabled" notification
- */
- public void setCookiesDisabledCaption(String cookiesDisabledCaption) {
- this.cookiesDisabledCaption = cookiesDisabledCaption;
- }
-
- /**
- * Sets the message of the "cookies disabled" notification. Set to null
- * for no message. If both caption and message is null, the notification
- * is disabled.
- *
- * @param cookiesDisabledMessage
- * the message for the "cookies disabled" notification
- */
- public void setCookiesDisabledMessage(String cookiesDisabledMessage) {
- this.cookiesDisabledMessage = cookiesDisabledMessage;
- }
-
- }
-
- /**
- * Application error is an error message defined on the application level.
- *
- * When an error occurs on the application level, this error message type
- * should be used. This indicates that the problem is caused by the
- * application - not by the user.
- */
- public class ApplicationError implements Terminal.ErrorEvent {
- private final Throwable throwable;
-
- public ApplicationError(Throwable throwable) {
- this.throwable = throwable;
- }
-
- @Override
- public Throwable getThrowable() {
- return throwable;
- }
-
- }
-
- /**
- * Gets the UI class for a request for which no UI is already known. This
- * method is called when the framework processes a request that does not
- * originate from an existing UI instance. This typically happens when a
- * host page is requested.
- * <p>
- * Subclasses of Application may override this method to provide custom
- * logic for choosing what kind of UI to use.
- * <p>
- * The default implementation in {@link Application} uses the
- * {@value #UI_PARAMETER} parameter from web.xml for finding the name of the
- * UI class. If {@link DeploymentConfiguration#getClassLoader()} does not
- * return <code>null</code>, the returned {@link ClassLoader} is used for
- * loading the UI class. Otherwise the {@link ClassLoader} used to load this
- * class is used.
- *
- * </p>
- *
- * @param request
- * the wrapped request for which a UI is needed
- * @return a UI instance to use for the request
- *
- * @see UI
- * @see WrappedRequest#getBrowserDetails()
- *
- * @since 7.0
- */
- public Class<? extends UI> getUIClass(WrappedRequest request) {
- // Iterate in reverse order - check newest provider first
- int providersSize = uiProviders.size();
- if (providersSize == 0) {
- throw new IllegalStateException("There are no UI providers");
- }
- for (int i = providersSize - 1; i >= 0; i--) {
- UIProvider provider = uiProviders.get(i);
-
- Class<? extends UI> uiClass = provider.getUIClass(this, request);
-
- if (uiClass != null) {
- return uiClass;
- }
- }
-
- throw new RuntimeException(
- "No UI provider returned an UI class for request");
- }
-
- /**
- * Creates an UI instance for a request for which no UI is already known.
- * This method is called when the framework processes a request that does
- * not originate from an existing UI instance. This typically happens when a
- * host page is requested.
- * <p>
- * Subclasses of Application may override this method to provide custom
- * logic for choosing how to create a suitable UI or for picking an already
- * created UI. If an existing UI is picked, care should be taken to avoid
- * keeping the same UI open in multiple browser windows, as that will cause
- * the states to go out of sync.
- * </p>
- *
- * @param request
- * @param uiClass
- * @return
- */
- protected <T extends UI> T createUIInstance(WrappedRequest request,
- Class<T> uiClass) {
- int providersSize = uiProviders.size();
- if (providersSize == 0) {
- throw new IllegalStateException("There are no UI providers");
- }
-
- for (int i = providersSize - 1; i >= 0; i--) {
- UIProvider provider = uiProviders.get(i);
-
- Class<? extends UI> providerClass = provider.getUIClass(this,
- request);
- if (providerClass != null) {
- if (providerClass != uiClass) {
- getLogger().warning(
- "Mismatching UI classes. Expected " + uiClass
- + " but got " + providerClass + " from "
- + provider);
- // Try with next provider if we didn't get the expected
- // class
- continue;
- }
- return uiClass.cast(provider.createInstance(this, uiClass,
- request));
+ 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);
}
}
-
- throw new RuntimeException(
- "No UI provider created an UI instance for request");
- }
-
- /**
- * Finds the theme to use for a specific UI. If no specific theme is
- * required, <code>null</code> is returned.
- *
- * TODO Tell what the default implementation does once it does something.
- *
- * @param uI
- * the UI to get a theme for
- * @return the name of the theme, or <code>null</code> if the default theme
- * should be used
- *
- * @since 7.0
- */
- public String getThemeForUI(WrappedRequest request,
- Class<? extends UI> uiClass) {
- Theme uiTheme = getAnnotationFor(uiClass, Theme.class);
- if (uiTheme != null) {
- return uiTheme.value();
- } else {
- return null;
+ UI.LegacyWindow window = getWindow(name);
+ if (window != null) {
+ return window;
}
+ return mainWindow;
}
/**
- * Finds the widgetset to use for a specific UI. If no specific widgetset is
- * required, <code>null</code> is returned.
+ * 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>
- * The default implementation uses the @{@link Widgetset} annotation if it's
- * defined for the UI class.
- *
- * @param request
- * the wrapped request for which to get a widgetset
- * @param uiClass
- * the UI class to get a widgetset for
- * @return the name of the widgetset, or <code>null</code> if the default
- * widgetset should be used
- *
- * @since 7.0
+ * {@inheritDoc}
*/
- public String getWidgetsetForUI(WrappedRequest request,
- Class<? extends UI> uiClass) {
- Widgetset uiWidgetset = getAnnotationFor(uiClass, Widgetset.class);
- if (uiWidgetset != null) {
- return uiWidgetset.value();
- } else {
+ @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;
}
}
/**
- * Helper to get an annotation for a class. If the annotation is not present
- * on the target class, it's superclasses and implemented interfaces are
- * also searched for the annotation.
- *
- * @param type
- * the target class from which the annotation should be found
- * @param annotationType
- * the annotation type to look for
- * @return an annotation of the given type, or <code>null</code> if the
- * annotation is not present on the class
- */
- private static <T extends Annotation> T getAnnotationFor(Class<?> type,
- Class<T> annotationType) {
- // Find from the class hierarchy
- Class<?> currentType = type;
- while (currentType != Object.class) {
- T annotation = currentType.getAnnotation(annotationType);
- if (annotation != null) {
- return annotation;
- } else {
- currentType = currentType.getSuperclass();
- }
- }
-
- // Find from an implemented interface
- for (Class<?> iface : type.getInterfaces()) {
- T annotation = iface.getAnnotation(annotationType);
- if (annotation != null) {
- return annotation;
- }
- }
-
- return null;
- }
-
- /**
- * Handles a request by passing it to each registered {@link RequestHandler}
- * in turn until one produces a response. This method is used for requests
- * that have not been handled by any specific functionality in the terminal
- * implementation (e.g. {@link VaadinServlet}).
- * <p>
- * The request handlers are invoked in the revere order in which they were
- * added to the application until a response has been produced. This means
- * that the most recently added handler is used first and the first request
- * handler that was added to the application is invoked towards the end
- * unless any previous handler has already produced a response.
- * </p>
- *
- * @param request
- * the wrapped request to get information from
- * @param response
- * the response to which data can be written
- * @return returns <code>true</code> if a {@link RequestHandler} has
- * produced a response and <code>false</code> if no response has
- * been written.
- * @throws IOException
- *
- * @see #addRequestHandler(RequestHandler)
- * @see RequestHandler
- *
- * @since 7.0
- */
- public boolean handleRequest(WrappedRequest request,
- WrappedResponse response) throws IOException {
- // Use a copy to avoid ConcurrentModificationException
- for (RequestHandler handler : new ArrayList<RequestHandler>(
- requestHandlers)) {
- if (handler.handleRequest(this, request, response)) {
- return true;
- }
- }
- // If not handled
- return false;
- }
-
- /**
- * Adds a request handler to this application. Request handlers can be added
- * to provide responses to requests that are not handled by the default
- * functionality of the framework.
+ * Sets the application's theme.
* <p>
- * Handlers are called in reverse order of addition, so the most recently
- * added handler will be called first.
+ * Note that this theme can be overridden for a specific UI with
+ * {@link VaadinSession#getThemeForUI(UI)}. Setting theme to be
+ * <code>null</code> selects the default theme. For the available theme
+ * names, see the contents of the VAADIN/themes directory.
* </p>
*
- * @param handler
- * the request handler to add
- *
- * @see #handleRequest(WrappedRequest, WrappedResponse)
- * @see #removeRequestHandler(RequestHandler)
- *
- * @since 7.0
+ * @param theme
+ * the new theme for this application.
*/
- public void addRequestHandler(RequestHandler handler) {
- requestHandlers.addFirst(handler);
+ public void setTheme(String theme) {
+ this.theme = theme;
}
/**
- * Removes a request handler from the application.
- *
- * @param handler
- * the request handler to remove
+ * Gets the application's theme. The application's theme is the default
+ * theme used by all the uIs for which a theme is not explicitly defined. If
+ * the application theme is not explicitly set, <code>null</code> is
+ * returned.
*
- * @since 7.0
+ * @return the name of the application's theme.
*/
- public void removeRequestHandler(RequestHandler handler) {
- requestHandlers.remove(handler);
+ public String getTheme() {
+ return theme;
}
/**
- * Gets the request handlers that are registered to the application. The
- * iteration order of the returned collection is the same as the order in
- * which the request handlers will be invoked when a request is handled.
- *
- * @return a collection of request handlers, with the iteration order
- * according to the order they would be invoked
- *
- * @see #handleRequest(WrappedRequest, WrappedResponse)
- * @see #addRequestHandler(RequestHandler)
- * @see #removeRequestHandler(RequestHandler)
- *
- * @since 7.0
- */
- public Collection<RequestHandler> getRequestHandlers() {
- return Collections.unmodifiableCollection(requestHandlers);
- }
-
- /**
- * Thread local for keeping track of currently used application instance
- *
- * @since 7.0
- */
- private static final ThreadLocal<Application> currentApplication = new ThreadLocal<Application>();
-
- /**
- * Gets the currently used application. The current application is
- * automatically defined when processing requests to the server. In other
- * cases, (e.g. from background threads), the current application is not
- * automatically defined.
- *
- * @return the current application instance if available, otherwise
- * <code>null</code>
- *
- * @see #setCurrent(Application)
- *
- * @since 7.0
- */
- public static Application getCurrent() {
- return currentApplication.get();
- }
-
- /**
- * Sets the thread local for the current application. This method is used by
- * the framework to set the current application whenever a new request is
- * processed and it is cleared when the request has been processed.
* <p>
- * The application developer can also use this method to define the current
- * application outside the normal request handling, e.g. when initiating
- * custom background threads.
+ * Gets a UI by name. Returns <code>null</code> if the application is not
+ * running or it does not contain a window corresponding to the name.
* </p>
*
- * @param application
- *
- * @see #getCurrent()
- * @see ThreadLocal
- *
- * @since 7.0
+ * @param name
+ * the name of the requested window
+ * @return a UI corresponding to the name, or <code>null</code> to use the
+ * default window
*/
- public static void setCurrent(Application application) {
- currentApplication.set(application);
+ public UI.LegacyWindow getWindow(String name) {
+ return legacyUINames.get(name);
}
/**
- * Check whether this application is in production mode. If an application
- * is in production mode, certain debugging facilities are not available.
- *
- * @return the status of the production mode flag
- *
- * @since 7.0
+ * Counter to get unique names for windows with no explicit name
*/
- public boolean isProductionMode() {
- return configuration.isProductionMode();
- }
-
- public void addUIProvider(UIProvider uIProvider) {
- uiProviders.add(uIProvider);
- }
-
- public void removeUIProvider(UIProvider uIProvider) {
- uiProviders.remove(uIProvider);
- }
+ private int namelessUIIndex = 0;
/**
- * Finds the {@link UI} to which a particular request belongs. If the
- * request originates from an existing UI, that UI is returned. In other
- * cases, the method attempts to create and initialize a new UI and might
- * throw a {@link UIRequiresMoreInformationException} if all required
- * information is not available.
- * <p>
- * Please note that this method can also return a newly created
- * <code>UI</code> which has not yet been initialized. You can use
- * {@link #isUIInitPending(int)} with the UI's id ( {@link UI#getUIId()} to
- * check whether the initialization is still pending.
- * </p>
- *
- * @param request
- * the request for which a UI is desired
- * @return a UI belonging to the request
+ * Adds a new browser level window to this application. Please note that UI
+ * doesn't have a name that is used in the URL - to add a named window you
+ * should instead use {@link #addWindow(UI, String)}
*
- * @see #createUI(WrappedRequest)
+ * @param uI
+ * the UI window to add to the application
+ * @return returns the name that has been assigned to the window
*
- * @since 7.0
+ * @see #addWindow(UI, String)
*/
- public UI getUIForRequest(WrappedRequest request) {
- UI uI = UI.getCurrent();
- if (uI != null) {
- return uI;
+ public void addWindow(UI.LegacyWindow uI) {
+ if (uI.getName() == null) {
+ String name = Integer.toString(namelessUIIndex++);
+ uI.setName(name);
}
- 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.");
- }
- }
- }
-
- } // end synchronized block
-
- UI.setCurrent(uI);
-
- return uI;
- }
-
- public UI createUI(WrappedRequest request) {
- Class<? extends UI> uiClass = getUIClass(request);
-
- UI ui = createUIInstance(request, uiClass);
-
- // Initialize some fields for a newly created UI
- if (ui.getApplication() == null) {
- ui.setApplication(this);
- }
- // Get the next id
- Integer uiId = Integer.valueOf(nextUIId++);
-
- uIs.put(uiId, ui);
-
- // Set thread local here so it is available in init
- UI.setCurrent(ui);
-
- ui.doInit(request, uiId.intValue());
-
- if (isUiPreserved(request, uiClass)) {
- // Remember this UI
- String windowName = request.getBrowserDetails().getWindowName();
- if (windowName == null) {
- getLogger().warning(
- "There is no window.name available for UI " + uiClass
- + " that should be preserved.");
- } else {
- retainOnRefreshUIs.put(windowName, uiId);
- }
- }
-
- return ui;
+ legacyUINames.put(uI.getName(), uI);
+ uI.setSession(VaadinSession.getCurrent());
}
/**
- * Internal helper to finds the UI id for a request.
- *
- * @param request
- * the request to get the UI id for
- * @return a UI id, or <code>null</code> if no UI id is defined
- *
- * @since 7.0
- */
- private static Integer getUIId(WrappedRequest request) {
- if (request instanceof CombinedRequest) {
- // Combined requests has the uiId parameter in the second request
- CombinedRequest combinedRequest = (CombinedRequest) request;
- request = combinedRequest.getSecondRequest();
- }
- String uiIdString = request.getParameter(UIConstants.UI_ID_PARAMETER);
- Integer uiId = uiIdString == null ? null : new Integer(uiIdString);
- return uiId;
- }
-
- /**
- * Checks whether the same UI state should be reused if the framework can
- * detect that the application is opened in a browser window where it has
- * previously been open. The framework attempts to discover this by checking
- * the value of window.name in the browser.
- *
- * @param request
- * @param uiClass
+ * Removes the specified window from the application. This also removes all
+ * name mappings for the window (see {@link #addWindow(UI, String) and
+ * #getWindowName(UI)}.
*
- * @return <code>true</code>if the same UI instance should be reused e.g.
- * when the browser window is refreshed.
- */
- public boolean isUiPreserved(WrappedRequest request,
- Class<? extends UI> uiClass) {
- PreserveOnRefresh preserveOnRefresh = getAnnotationFor(uiClass,
- PreserveOnRefresh.class);
- return preserveOnRefresh != null;
- }
-
- /**
- * Gets all the uIs of this application. This includes uIs that have been
- * requested but not yet initialized. Please note, that uIs are not
- * automatically removed e.g. if the browser window is closed and that there
- * is no way to manually remove a UI. Inactive uIs will thus not be released
- * for GC until the entire application is released when the session has
- * timed out (unless there are dangling references). Improved support for
- * releasing unused uIs is planned for an upcoming alpha release of Vaadin
- * 7.
- *
- * @return a collection of uIs belonging to this application
- *
- * @since 7.0
- */
- public Collection<UI> getUIs() {
- return Collections.unmodifiableCollection(uIs.values());
- }
-
- private int connectorIdSequence = 0;
-
- /**
- * Generate an id for the given Connector. Connectors must not call this
- * method more than once, the first time they need an id.
- *
- * @param connector
- * A connector that has not yet been assigned an id.
- * @return A new id for the connector
- */
- public String createConnectorId(ClientConnector connector) {
- return String.valueOf(connectorIdSequence++);
- }
-
- private static final Logger getLogger() {
- return Logger.getLogger(Application.class.getName());
- }
-
- /**
- * Returns a UI with the given id.
* <p>
- * This is meant for framework internal use.
+ * Note that removing window from the application does not close the browser
+ * window - the window is only removed from the server-side.
* </p>
*
- * @param uiId
- * The UI id
- * @return The UI with the given id or null if not found
- */
- public UI getUIById(int uiId) {
- return uIs.get(uiId);
- }
-
- /**
- * Adds a listener that will be invoked when the bootstrap HTML is about to
- * be generated. This can be used to modify the contents of the HTML that
- * loads the Vaadin application in the browser and the HTTP headers that are
- * included in the response serving the HTML.
- *
- * @see BootstrapListener#modifyBootstrapFragment(BootstrapFragmentResponse)
- * @see BootstrapListener#modifyBootstrapPage(BootstrapPageResponse)
- *
- * @param listener
- * the bootstrap listener to add
- */
- public void addBootstrapListener(BootstrapListener listener) {
- eventRouter.addListener(BootstrapFragmentResponse.class, listener,
- BOOTSTRAP_FRAGMENT_METHOD);
- eventRouter.addListener(BootstrapPageResponse.class, listener,
- BOOTSTRAP_PAGE_METHOD);
- }
-
- /**
- * Remove a bootstrap listener that was previously added.
- *
- * @see #addBootstrapListener(BootstrapListener)
- *
- * @param listener
- * the bootstrap listener to remove
- */
- public void removeBootstrapListener(BootstrapListener listener) {
- eventRouter.removeListener(BootstrapFragmentResponse.class, listener,
- BOOTSTRAP_FRAGMENT_METHOD);
- eventRouter.removeListener(BootstrapPageResponse.class, listener,
- BOOTSTRAP_PAGE_METHOD);
- }
-
- /**
- * Fires a bootstrap event to all registered listeners. There are currently
- * two supported events, both inheriting from {@link BootstrapResponse}:
- * {@link BootstrapFragmentResponse} and {@link BootstrapPageResponse}.
- *
- * @param response
- * the bootstrap response event for which listeners should be
- * fired
- */
- public void modifyBootstrapResponse(BootstrapResponse response) {
- eventRouter.fireEvent(response);
- }
-
- /**
- * Removes all those UIs from the application for which {@link #isUIAlive}
- * returns false. Close events are fired for the removed UIs.
- * <p>
- * Called by the framework at the end of every request.
- *
- * @see UI.CloseEvent
- * @see UI.CloseListener
- * @see #isUIAlive(UI)
- *
- * @since 7.0.0
+ * @param uI
+ * the UI to remove
*/
- public void closeInactiveUIs() {
- for (Iterator<UI> i = uIs.values().iterator(); i.hasNext();) {
- UI ui = i.next();
- if (!isUIAlive(ui)) {
- i.remove();
- retainOnRefreshUIs.values().remove(ui.getUIId());
- ui.fireCloseEvent();
- getLogger().info(
- "Closed UI #" + ui.getUIId() + " due to inactivity");
+ public void removeWindow(UI.LegacyWindow uI) {
+ for (Entry<String, UI.LegacyWindow> entry : legacyUINames.entrySet()) {
+ if (entry.getValue() == uI) {
+ legacyUINames.remove(entry.getKey());
}
}
}
/**
- * 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
- * application. This is a lower bound; it might take longer to close an
- * inactive UI. Returns a negative number if heartbeat is disabled and
- * timeout never occurs.
+ * Gets the set of windows contained by the application.
*
- * @see #getUidlRequestTimeout()
- * @see #closeInactiveUIs()
- * @see DeploymentConfiguration#getHeartbeatInterval()
- *
- * @since 7.0.0
+ * <p>
+ * Note that the returned set of windows can not be modified.
+ * </p>
*
- * @return The heartbeat timeout in seconds or a negative number if timeout
- * never occurs.
+ * @return the unmodifiable collection of windows.
*/
- protected int getHeartbeatTimeout() {
- // Permit three missed heartbeats before closing the UI
- return (int) (configuration.getHeartbeatInterval() * (3.1));
+ public Collection<UI.LegacyWindow> getWindows() {
+ return Collections.unmodifiableCollection(legacyUINames.values());
}
- /**
- * Returns the number of seconds that must pass without a valid UIDL request
- * being received from a UI before the UI is removed from the application,
- * even though heartbeat requests are received. This is a lower bound; it
- * might take longer to close an inactive UI. Returns a negative number if
- * <p>
- * This timeout only has effect if cleanup of inactive UIs is enabled;
- * otherwise heartbeat requests are enough to extend UI lifetime
- * indefinitely.
- *
- * @see DeploymentConfiguration#isIdleUICleanupEnabled()
- * @see #getHeartbeatTimeout()
- * @see #closeInactiveUIs()
- *
- * @since 7.0.0
- *
- * @return The UIDL request timeout in seconds, or a negative number if
- * timeout never occurs.
- */
- protected int getUidlRequestTimeout() {
- return configuration.isIdleUICleanupEnabled() ? getContext()
- .getMaxInactiveInterval() : -1;
+ @Override
+ public void terminalError(ErrorEvent event) {
+ VaadinSession.getCurrent().terminalError(event);
}
- /**
- * Returns whether the given UI is alive (the client-side actively
- * communicates with the server) or whether it can be removed from the
- * application and eventually collected.
- *
- * @since 7.0.0
- *
- * @param ui
- * The UI whose status to check
- * @return true if the UI is alive, false if it could be removed.
- */
- protected boolean isUIAlive(UI ui) {
- long now = System.currentTimeMillis();
- if (getHeartbeatTimeout() >= 0
- && now - ui.getLastHeartbeatTime() > 1000 * getHeartbeatTimeout()) {
- return false;
- }
- if (getUidlRequestTimeout() >= 0
- && now - ui.getLastUidlRequestTime() > 1000 * getUidlRequestTimeout()) {
- return false;
- }
- return true;
+ public VaadinSession getContext() {
+ return VaadinSession.getCurrent();
}
- /**
- * Gets this application's global resource handler that takes care of
- * serving connector resources that are not served by any single connector
- * because e.g. because they are served with strong caching or because of
- * legacy reasons.
- *
- * @param createOnDemand
- * <code>true</code> if a resource handler should be initialized
- * if there is no handler associated with this application.
- * </code>false</code> if </code>null</code> should be returned
- * if there is no registered handler.
- * @return this application's global resource handler, or <code>null</code>
- * if there is no handler and the createOnDemand parameter is
- * <code>false</code>.
- *
- * @since 7.0.0
- */
- public GlobalResourceHandler getGlobalResourceHandler(boolean createOnDemand) {
- if (globalResourceHandler == null && createOnDemand) {
- globalResourceHandler = new GlobalResourceHandler();
- addRequestHandler(globalResourceHandler);
- }
+ protected void close() {
+ VaadinSession.getCurrent().close();
+ }
- return globalResourceHandler;
+ public boolean isRunning() {
+ return VaadinSession.getCurrent().isRunning();
}
- public String getPageTitleForUI(WrappedRequest request,
- Class<? extends UI> uiClass) {
- Title titleAnnotation = getAnnotationFor(uiClass, Title.class);
- if (titleAnnotation == null) {
- return null;
- } else {
- return titleAnnotation.value();
- }
+ public URL getURL() {
+ return VaadinSession.getCurrent().getURL();
}
-}
+} \ No newline at end of file
diff --git a/server/src/com/vaadin/DefaultApplicationConfiguration.java b/server/src/com/vaadin/DefaultApplicationConfiguration.java
new file mode 100644
index 0000000000..2e2267193e
--- /dev/null
+++ b/server/src/com/vaadin/DefaultApplicationConfiguration.java
@@ -0,0 +1,229 @@
+/*
+ * 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;
+
+import java.util.Properties;
+import java.util.logging.Logger;
+
+import com.vaadin.server.ApplicationConfiguration;
+import com.vaadin.server.Constants;
+
+public class DefaultApplicationConfiguration implements
+ ApplicationConfiguration {
+ private final Properties applicationProperties;
+ private boolean productionMode;
+ private boolean xsrfProtectionEnabled;
+ private int resourceCacheTime;
+ private int heartbeatInterval;
+ private boolean idleRootCleanupEnabled;
+ private final Class<?> systemPropertyBaseClass;
+
+ public DefaultApplicationConfiguration(Class<?> systemPropertyBaseClass,
+ Properties applicationProperties) {
+ this.applicationProperties = applicationProperties;
+ this.systemPropertyBaseClass = systemPropertyBaseClass;
+
+ checkProductionMode();
+ checkXsrfProtection();
+ checkResourceCacheTime();
+ checkHeartbeatInterval();
+ checkIdleUICleanup();
+ }
+
+ @Override
+ public String getApplicationOrSystemProperty(String propertyName,
+ String defaultValue) {
+ String val = null;
+
+ // Try application properties
+ val = getApplicationProperty(propertyName);
+ if (val != null) {
+ return val;
+ }
+
+ // Try system properties
+ val = getSystemProperty(propertyName);
+ if (val != null) {
+ return val;
+ }
+
+ return defaultValue;
+ }
+
+ /**
+ * Gets an system property value.
+ *
+ * @param parameterName
+ * the Name or the parameter.
+ * @return String value or null if not found
+ */
+ protected String getSystemProperty(String parameterName) {
+ String val = null;
+
+ String pkgName;
+ final Package pkg = systemPropertyBaseClass.getPackage();
+ if (pkg != null) {
+ pkgName = pkg.getName();
+ } else {
+ final String className = systemPropertyBaseClass.getName();
+ pkgName = new String(className.toCharArray(), 0,
+ className.lastIndexOf('.'));
+ }
+ val = System.getProperty(pkgName + "." + parameterName);
+ if (val != null) {
+ return val;
+ }
+
+ // Try lowercased system properties
+ val = System.getProperty(pkgName + "." + parameterName.toLowerCase());
+ return val;
+ }
+
+ /**
+ * Gets an application property value.
+ *
+ * @param parameterName
+ * the Name or the parameter.
+ * @return String value or null if not found
+ */
+ public String getApplicationProperty(String parameterName) {
+
+ String val = applicationProperties.getProperty(parameterName);
+ if (val != null) {
+ return val;
+ }
+
+ // Try lower case application properties for backward compatibility with
+ // 3.0.2 and earlier
+ val = applicationProperties.getProperty(parameterName.toLowerCase());
+
+ return val;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * The default is false.
+ */
+ @Override
+ public boolean isProductionMode() {
+ return productionMode;
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * The default is true.
+ */
+ @Override
+ public boolean isXsrfProtectionEnabled() {
+ return xsrfProtectionEnabled;
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * The default interval is 3600 seconds (1 hour).
+ */
+ @Override
+ public int getResourceCacheTime() {
+ return resourceCacheTime;
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * The default interval is 300 seconds (5 minutes).
+ */
+ @Override
+ public int getHeartbeatInterval() {
+ return heartbeatInterval;
+ }
+
+ @Override
+ public boolean isIdleUICleanupEnabled() {
+ return idleRootCleanupEnabled;
+ }
+
+ /**
+ * Log a warning if Vaadin is not running in production mode.
+ */
+ private void checkProductionMode() {
+ productionMode = getApplicationOrSystemProperty(
+ Constants.SERVLET_PARAMETER_PRODUCTION_MODE, "false").equals(
+ "true");
+ if (!productionMode) {
+ getLogger().warning(Constants.NOT_PRODUCTION_MODE_INFO);
+ }
+ }
+
+ /**
+ * Log a warning if cross-site request forgery protection is disabled.
+ */
+ private void checkXsrfProtection() {
+ xsrfProtectionEnabled = !getApplicationOrSystemProperty(
+ Constants.SERVLET_PARAMETER_DISABLE_XSRF_PROTECTION, "false")
+ .equals("true");
+ if (!xsrfProtectionEnabled) {
+ getLogger().warning(Constants.WARNING_XSRF_PROTECTION_DISABLED);
+ }
+ }
+
+ /**
+ * Log a warning if resource cache time is set but is not an integer.
+ */
+ private void checkResourceCacheTime() {
+ try {
+ resourceCacheTime = Integer
+ .parseInt(getApplicationOrSystemProperty(
+ Constants.SERVLET_PARAMETER_RESOURCE_CACHE_TIME,
+ "3600"));
+ } catch (NumberFormatException e) {
+ getLogger().warning(
+ Constants.WARNING_RESOURCE_CACHING_TIME_NOT_NUMERIC);
+ resourceCacheTime = 3600;
+ }
+ }
+
+ private void checkHeartbeatInterval() {
+ try {
+ heartbeatInterval = Integer
+ .parseInt(getApplicationOrSystemProperty(
+ Constants.SERVLET_PARAMETER_HEARTBEAT_RATE, "300"));
+ } catch (NumberFormatException e) {
+ getLogger().warning(
+ Constants.WARNING_HEARTBEAT_INTERVAL_NOT_NUMERIC);
+ heartbeatInterval = 300;
+ }
+ }
+
+ private void checkIdleUICleanup() {
+ idleRootCleanupEnabled = getApplicationOrSystemProperty(
+ Constants.SERVLET_PARAMETER_CLOSE_IDLE_UIS, "false").equals(
+ "true");
+ }
+
+ private Logger getLogger() {
+ return Logger.getLogger(getClass().getName());
+ }
+
+ @Override
+ public Properties getInitParameters() {
+ return applicationProperties;
+ }
+
+}
diff --git a/server/src/com/vaadin/data/util/converter/ConverterUtil.java b/server/src/com/vaadin/data/util/converter/ConverterUtil.java
index 36cd6d0859..a6014bb3eb 100644
--- a/server/src/com/vaadin/data/util/converter/ConverterUtil.java
+++ b/server/src/com/vaadin/data/util/converter/ConverterUtil.java
@@ -18,7 +18,7 @@ package com.vaadin.data.util.converter;
import java.io.Serializable;
import java.util.Locale;
-import com.vaadin.Application;
+import com.vaadin.server.VaadinSession;
public class ConverterUtil implements Serializable {
@@ -26,7 +26,7 @@ public class ConverterUtil implements Serializable {
* Finds a converter that can convert from the given presentation type to
* the given model type and back. Uses the given application to find a
* {@link ConverterFactory} or, if application is null, uses the
- * {@link Application#getCurrent()}.
+ * {@link VaadinSession#getCurrent()}.
*
* @param <PRESENTATIONTYPE>
* The presentation type
@@ -44,10 +44,10 @@ public class ConverterUtil implements Serializable {
*/
public static <PRESENTATIONTYPE, MODELTYPE> Converter<PRESENTATIONTYPE, MODELTYPE> getConverter(
Class<PRESENTATIONTYPE> presentationType,
- Class<MODELTYPE> modelType, Application application) {
+ Class<MODELTYPE> modelType, VaadinSession application) {
Converter<PRESENTATIONTYPE, MODELTYPE> converter = null;
if (application == null) {
- application = Application.getCurrent();
+ application = VaadinSession.getCurrent();
}
if (application != null) {
diff --git a/server/src/com/vaadin/data/util/converter/DefaultConverterFactory.java b/server/src/com/vaadin/data/util/converter/DefaultConverterFactory.java
index ffd432076f..17b89ccb20 100644
--- a/server/src/com/vaadin/data/util/converter/DefaultConverterFactory.java
+++ b/server/src/com/vaadin/data/util/converter/DefaultConverterFactory.java
@@ -19,14 +19,14 @@ package com.vaadin.data.util.converter;
import java.util.Date;
import java.util.logging.Logger;
-import com.vaadin.Application;
+import com.vaadin.server.VaadinSession;
/**
* Default implementation of {@link ConverterFactory}. Provides converters for
* standard types like {@link String}, {@link Double} and {@link Date}. </p>
* <p>
* Custom converters can be provided by extending this class and using
- * {@link Application#setConverterFactory(ConverterFactory)}.
+ * {@link VaadinSession#setConverterFactory(ConverterFactory)}.
* </p>
*
* @author Vaadin Ltd
diff --git a/server/src/com/vaadin/event/dd/acceptcriteria/SourceIs.java b/server/src/com/vaadin/event/dd/acceptcriteria/SourceIs.java
index 6258aed423..dee807c610 100644
--- a/server/src/com/vaadin/event/dd/acceptcriteria/SourceIs.java
+++ b/server/src/com/vaadin/event/dd/acceptcriteria/SourceIs.java
@@ -48,7 +48,7 @@ public class SourceIs extends ClientSideCriterion {
int paintedComponents = 0;
for (int i = 0; i < components.length; i++) {
Component c = components[i];
- if (c.getApplication() != null) {
+ if (c.getUI() != null && c.getUI().getSession() != null) {
target.addAttribute("component" + paintedComponents++, c);
} else {
Logger.getLogger(SourceIs.class.getName())
diff --git a/server/src/com/vaadin/server/AbstractClientConnector.java b/server/src/com/vaadin/server/AbstractClientConnector.java
index 09e366260b..f8fbbeeb4c 100644
--- a/server/src/com/vaadin/server/AbstractClientConnector.java
+++ b/server/src/com/vaadin/server/AbstractClientConnector.java
@@ -31,7 +31,6 @@ import java.util.Map;
import java.util.NoSuchElementException;
import java.util.logging.Logger;
-import com.vaadin.Application;
import com.vaadin.external.json.JSONException;
import com.vaadin.external.json.JSONObject;
import com.vaadin.shared.communication.ClientRpc;
@@ -343,11 +342,11 @@ public abstract class AbstractClientConnector implements ClientConnector {
@Override
public String getConnectorId() {
if (connectorId == null) {
- if (getApplication() == null) {
+ if (getSession() == null) {
throw new RuntimeException(
"Component must be attached to an application when getConnectorId() is called for the first time");
}
- connectorId = getApplication().createConnectorId(this);
+ connectorId = getSession().createConnectorId(this);
}
return connectorId;
}
@@ -358,12 +357,12 @@ public abstract class AbstractClientConnector implements ClientConnector {
*
* @return The connector's application, or <code>null</code> if not attached
*/
- protected Application getApplication() {
+ protected VaadinSession getSession() {
UI uI = getUI();
if (uI == null) {
return null;
} else {
- return uI.getApplication();
+ return uI.getSession();
}
}
@@ -502,7 +501,7 @@ public abstract class AbstractClientConnector implements ClientConnector {
}
// Send detach event if the component have been connected to a window
- if (getApplication() != null) {
+ if (getSession() != null) {
detach();
}
@@ -510,7 +509,7 @@ public abstract class AbstractClientConnector implements ClientConnector {
this.parent = parent;
// Send attach event if connected to an application
- if (getApplication() != null) {
+ if (getSession() != null) {
attach();
}
}
@@ -536,7 +535,7 @@ public abstract class AbstractClientConnector implements ClientConnector {
* {@inheritDoc}
*
* <p>
- * The {@link #getApplication()} and {@link #getUI()} methods might return
+ * The {@link #getSession()} and {@link #getUI()} methods might return
* <code>null</code> after this method is called.
* </p>
*/
diff --git a/server/src/com/vaadin/server/AbstractCommunicationManager.java b/server/src/com/vaadin/server/AbstractCommunicationManager.java
index 02d0b0d791..4f408d6fe9 100644
--- a/server/src/com/vaadin/server/AbstractCommunicationManager.java
+++ b/server/src/com/vaadin/server/AbstractCommunicationManager.java
@@ -56,7 +56,6 @@ import java.util.logging.Logger;
import javax.servlet.http.HttpServletResponse;
-import com.vaadin.Application;
import com.vaadin.annotations.JavaScript;
import com.vaadin.annotations.StyleSheet;
import com.vaadin.external.json.JSONArray;
@@ -143,7 +142,7 @@ public abstract class AbstractCommunicationManager implements Serializable {
/**
* The application this communication manager is used for
*/
- private final Application application;
+ private final VaadinSession application;
private List<String> locales;
@@ -170,7 +169,7 @@ public abstract class AbstractCommunicationManager implements Serializable {
*
* @param application
*/
- public AbstractCommunicationManager(Application application) {
+ public AbstractCommunicationManager(VaadinSession application) {
this.application = application;
application.addRequestHandler(getBootstrapHandler());
application.addRequestHandler(UNSUPPORTED_BROWSER_HANDLER);
@@ -178,7 +177,7 @@ public abstract class AbstractCommunicationManager implements Serializable {
requireLocale(application.getLocale().toString());
}
- protected Application getApplication() {
+ protected VaadinSession getApplication() {
return application;
}
@@ -366,7 +365,7 @@ public abstract class AbstractCommunicationManager implements Serializable {
"StreamVariable for the post not found");
}
- final Application application = getApplication();
+ final VaadinSession application = getApplication();
OutputStream out = null;
int totalBytes = 0;
@@ -491,7 +490,7 @@ public abstract class AbstractCommunicationManager implements Serializable {
* Internally process a UIDL request from the client.
*
* This method calls
- * {@link #handleVariables(WrappedRequest, WrappedResponse, Callback, Application, UI)}
+ * {@link #handleVariables(WrappedRequest, WrappedResponse, Callback, VaadinSession, UI)}
* to process any changes to variables by the client and then repaints
* affected components using {@link #paintAfterVariableChanges()}.
*
@@ -518,7 +517,8 @@ public abstract class AbstractCommunicationManager implements Serializable {
checkWidgetsetVersion(request);
requestThemeName = request.getParameter("theme");
- maxInactiveInterval = request.getSessionMaxInactiveInterval();
+ maxInactiveInterval = request.getWrappedSession()
+ .getMaxInactiveInterval();
// repaint requested or session has timed out and new one is created
boolean repaintAll;
final OutputStream out;
@@ -676,7 +676,7 @@ public abstract class AbstractCommunicationManager implements Serializable {
}
sb.append("\nComponent hierarchy:\n");
- Application application2 = component.getApplication();
+ VaadinSession application2 = component.getUI().getSession();
sb.append(application2.getClass().getName());
sb.append(".");
sb.append(application2.getClass().getSimpleName());
@@ -772,12 +772,13 @@ public abstract class AbstractCommunicationManager implements Serializable {
*/
protected String getSecurityKey(WrappedRequest request) {
String seckey = null;
- seckey = (String) request
- .getSessionAttribute(ApplicationConstants.UIDL_SECURITY_TOKEN_ID);
+ WrappedSession session = request.getWrappedSession();
+ seckey = (String) session
+ .getAttribute(ApplicationConstants.UIDL_SECURITY_TOKEN_ID);
if (seckey == null) {
seckey = UUID.randomUUID().toString();
- request.setSessionAttribute(
- ApplicationConstants.UIDL_SECURITY_TOKEN_ID, seckey);
+ session.setAttribute(ApplicationConstants.UIDL_SECURITY_TOKEN_ID,
+ seckey);
}
return seckey;
@@ -788,7 +789,7 @@ public abstract class AbstractCommunicationManager implements Serializable {
final PrintWriter outWriter, UI ui, boolean analyzeLayouts)
throws PaintException, JSONException {
ArrayList<ClientConnector> dirtyVisibleConnectors = new ArrayList<ClientConnector>();
- Application application = ui.getApplication();
+ VaadinSession application = ui.getSession();
// Paints components
ConnectorTracker uiConnectorTracker = ui.getConnectorTracker();
getLogger().log(Level.FINE, "* Creating response to client");
@@ -1311,9 +1312,9 @@ public abstract class AbstractCommunicationManager implements Serializable {
* response.
*/
private void writePerformanceData(final PrintWriter outWriter) {
- ApplicationContext ctx = application.getContext();
outWriter.write(String.format(", \"timings\":[%d, %d]",
- ctx.getTotalSessionTime(), ctx.getLastRequestTime()));
+ application.getTotalSessionTime(),
+ application.getLastRequestTime()));
}
private void legacyPaint(PaintTarget paintTarget,
@@ -1519,10 +1520,8 @@ public abstract class AbstractCommunicationManager implements Serializable {
* @param application
* @return false if the XSRF is turned off, true otherwise
*/
- public boolean isXSRFEnabled(Application application) {
- return !"true"
- .equals(application
- .getProperty(VaadinServlet.SERVLET_PARAMETER_DISABLE_XSRF_PROTECTION));
+ public boolean isXSRFEnabled(VaadinSession application) {
+ return application.getConfiguration().isXsrfProtectionEnabled();
}
/**
@@ -1536,7 +1535,7 @@ public abstract class AbstractCommunicationManager implements Serializable {
*/
private boolean handleVariables(WrappedRequest request,
WrappedResponse response, Callback callback,
- Application application2, UI uI) throws IOException,
+ VaadinSession application2, UI uI) throws IOException,
InvalidUIDLSecurityKeyException, JSONException {
boolean success = true;
@@ -1559,7 +1558,9 @@ public abstract class AbstractCommunicationManager implements Serializable {
// ApplicationServlet has stored the security token in the
// session; check that it matched the one sent in the UIDL
String sessId = (String) request
- .getSessionAttribute(ApplicationConstants.UIDL_SECURITY_TOKEN_ID);
+ .getWrappedSession()
+ .getAttribute(
+ ApplicationConstants.UIDL_SECURITY_TOKEN_ID);
if (sessId == null || !sessId.equals(bursts[0])) {
throw new InvalidUIDLSecurityKeyException(
@@ -1696,7 +1697,7 @@ public abstract class AbstractCommunicationManager implements Serializable {
if (connector instanceof Component) {
errorComponent = (Component) connector;
}
- handleChangeVariablesError(uI.getApplication(),
+ handleChangeVariablesError(uI.getSession(),
errorComponent, realException, null);
}
} else {
@@ -1728,7 +1729,7 @@ public abstract class AbstractCommunicationManager implements Serializable {
errorComponent = (Component) dropHandlerOwner;
}
}
- handleChangeVariablesError(uI.getApplication(),
+ handleChangeVariablesError(uI.getSession(),
errorComponent, e, changes);
}
}
@@ -1941,7 +1942,7 @@ public abstract class AbstractCommunicationManager implements Serializable {
* @param m
* map from variable names to values
*/
- private void handleChangeVariablesError(Application application,
+ private void handleChangeVariablesError(VaadinSession application,
Component owner, Throwable t, Map<String, Object> m) {
boolean handled = false;
ChangeVariablesErrorEvent errorEvent = new ChangeVariablesErrorEvent(
@@ -2153,8 +2154,8 @@ public abstract class AbstractCommunicationManager implements Serializable {
* Ends the Application.
*
* The browser is redirected to the Application logout URL set with
- * {@link Application#setLogoutURL(String)}, or to the application URL if no
- * logout URL is given.
+ * {@link VaadinSession#setLogoutURL(String)}, or to the application URL if
+ * no logout URL is given.
*
* @param request
* the request instance.
@@ -2166,7 +2167,7 @@ public abstract class AbstractCommunicationManager implements Serializable {
* if the writing failed due to input/output error.
*/
private void endApplication(WrappedRequest request,
- WrappedResponse response, Application application)
+ WrappedResponse response, VaadinSession application)
throws IOException {
String logoutUrl = application.getLogoutURL();
@@ -2392,7 +2393,7 @@ public abstract class AbstractCommunicationManager implements Serializable {
}
public void handleBrowserDetailsRequest(WrappedRequest request,
- WrappedResponse response, Application application)
+ WrappedResponse response, VaadinSession application)
throws IOException {
assert UI.getCurrent() == null;
@@ -2449,7 +2450,7 @@ public abstract class AbstractCommunicationManager implements Serializable {
StringWriter sWriter = new StringWriter();
PrintWriter pWriter = new PrintWriter(sWriter);
pWriter.print("{");
- if (isXSRFEnabled(uI.getApplication())) {
+ if (isXSRFEnabled(uI.getSession())) {
pWriter.print(getSecurityKeyUIDL(request));
}
writeUidlResponse(request, true, pWriter, uI, false);
@@ -2570,7 +2571,7 @@ public abstract class AbstractCommunicationManager implements Serializable {
* @throws IOException
* @throws InvalidUIDLSecurityKeyException
*/
- public void handleFileUpload(Application application,
+ public void handleFileUpload(VaadinSession application,
WrappedRequest request, WrappedResponse response)
throws IOException, InvalidUIDLSecurityKeyException {
@@ -2632,7 +2633,7 @@ public abstract class AbstractCommunicationManager implements Serializable {
* @throws IOException
*/
public void handleHeartbeatRequest(WrappedRequest request,
- WrappedResponse response, Application application)
+ WrappedResponse response, VaadinSession application)
throws IOException {
UI ui = null;
try {
diff --git a/server/src/com/vaadin/server/AbstractDeploymentConfiguration.java b/server/src/com/vaadin/server/AbstractDeploymentConfiguration.java
index d1280d29ce..3d7efa6711 100644
--- a/server/src/com/vaadin/server/AbstractDeploymentConfiguration.java
+++ b/server/src/com/vaadin/server/AbstractDeploymentConfiguration.java
@@ -18,87 +18,28 @@ package com.vaadin.server;
import java.lang.reflect.Constructor;
import java.util.Iterator;
-import java.util.Properties;
import java.util.ServiceLoader;
-import java.util.logging.Logger;
public abstract class AbstractDeploymentConfiguration implements
DeploymentConfiguration {
- private final Class<?> systemPropertyBaseClass;
- private final Properties applicationProperties;
private AddonContext addonContext;
- private boolean productionMode;
- private boolean xsrfProtectionEnabled;
- private int resourceCacheTime;
- private int heartbeatInterval;
- private boolean idleRootCleanupEnabled;
+ private final ApplicationConfiguration applicationConfiguration;
- public AbstractDeploymentConfiguration(Class<?> systemPropertyBaseClass,
- Properties applicationProperties) {
- this.systemPropertyBaseClass = systemPropertyBaseClass;
- this.applicationProperties = applicationProperties;
-
- checkProductionMode();
- checkXsrfProtection();
- checkResourceCacheTime();
- checkHeartbeatInterval();
- checkIdleUICleanup();
+ public AbstractDeploymentConfiguration(
+ ApplicationConfiguration applicationConfiguration) {
+ this.applicationConfiguration = applicationConfiguration;
}
@Override
- public String getApplicationOrSystemProperty(String propertyName,
- String defaultValue) {
- String val = null;
-
- // Try application properties
- val = getApplicationProperty(propertyName);
- if (val != null) {
- return val;
- }
-
- // Try system properties
- val = getSystemProperty(propertyName);
- if (val != null) {
- return val;
- }
-
- return defaultValue;
- }
-
- /**
- * Gets an system property value.
- *
- * @param parameterName
- * the Name or the parameter.
- * @return String value or null if not found
- */
- protected String getSystemProperty(String parameterName) {
- String val = null;
-
- String pkgName;
- final Package pkg = systemPropertyBaseClass.getPackage();
- if (pkg != null) {
- pkgName = pkg.getName();
- } else {
- final String className = systemPropertyBaseClass.getName();
- pkgName = new String(className.toCharArray(), 0,
- className.lastIndexOf('.'));
- }
- val = System.getProperty(pkgName + "." + parameterName);
- if (val != null) {
- return val;
- }
-
- // Try lowercased system properties
- val = System.getProperty(pkgName + "." + parameterName.toLowerCase());
- return val;
+ public ApplicationConfiguration getApplicationConfiguration() {
+ return applicationConfiguration;
}
@Override
public ClassLoader getClassLoader() {
- final String classLoaderName = getApplicationOrSystemProperty(
- "ClassLoader", null);
+ final String classLoaderName = getApplicationConfiguration()
+ .getApplicationOrSystemProperty("ClassLoader", null);
ClassLoader classLoader;
if (classLoaderName == null) {
classLoader = getClass().getClassLoader();
@@ -119,32 +60,6 @@ public abstract class AbstractDeploymentConfiguration implements
return classLoader;
}
- /**
- * Gets an application property value.
- *
- * @param parameterName
- * the Name or the parameter.
- * @return String value or null if not found
- */
- protected String getApplicationProperty(String parameterName) {
-
- String val = applicationProperties.getProperty(parameterName);
- if (val != null) {
- return val;
- }
-
- // Try lower case application properties for backward compatibility with
- // 3.0.2 and earlier
- val = applicationProperties.getProperty(parameterName.toLowerCase());
-
- return val;
- }
-
- @Override
- public Properties getInitParameters() {
- return applicationProperties;
- }
-
@Override
public Iterator<AddonContextListener> getAddonContextListeners() {
// Called once for init and then no more, so there's no point in caching
@@ -163,111 +78,4 @@ public abstract class AbstractDeploymentConfiguration implements
public AddonContext getAddonContext() {
return addonContext;
}
-
- /**
- * {@inheritDoc}
- *
- * The default is false.
- */
- @Override
- public boolean isProductionMode() {
- return productionMode;
- }
-
- /**
- * {@inheritDoc}
- *
- * The default is true.
- */
- @Override
- public boolean isXsrfProtectionEnabled() {
- return xsrfProtectionEnabled;
- }
-
- /**
- * {@inheritDoc}
- *
- * The default interval is 3600 seconds (1 hour).
- */
- @Override
- public int getResourceCacheTime() {
- return resourceCacheTime;
- }
-
- /**
- * {@inheritDoc}
- *
- * The default interval is 300 seconds (5 minutes).
- */
- @Override
- public int getHeartbeatInterval() {
- return heartbeatInterval;
- }
-
- @Override
- public boolean isIdleUICleanupEnabled() {
- return idleRootCleanupEnabled;
- }
-
- /**
- * Log a warning if Vaadin is not running in production mode.
- */
- private void checkProductionMode() {
- productionMode = getApplicationOrSystemProperty(
- Constants.SERVLET_PARAMETER_PRODUCTION_MODE, "false").equals(
- "true");
- if (!productionMode) {
- getLogger().warning(Constants.NOT_PRODUCTION_MODE_INFO);
- }
- }
-
- /**
- * Log a warning if cross-site request forgery protection is disabled.
- */
- private void checkXsrfProtection() {
- xsrfProtectionEnabled = !getApplicationOrSystemProperty(
- Constants.SERVLET_PARAMETER_DISABLE_XSRF_PROTECTION, "false")
- .equals("true");
- if (!xsrfProtectionEnabled) {
- getLogger().warning(Constants.WARNING_XSRF_PROTECTION_DISABLED);
- }
- }
-
- /**
- * Log a warning if resource cache time is set but is not an integer.
- */
- private void checkResourceCacheTime() {
- try {
- resourceCacheTime = Integer
- .parseInt(getApplicationOrSystemProperty(
- Constants.SERVLET_PARAMETER_RESOURCE_CACHE_TIME,
- "3600"));
- } catch (NumberFormatException e) {
- getLogger().warning(
- Constants.WARNING_RESOURCE_CACHING_TIME_NOT_NUMERIC);
- resourceCacheTime = 3600;
- }
- }
-
- private void checkHeartbeatInterval() {
- try {
- heartbeatInterval = Integer
- .parseInt(getApplicationOrSystemProperty(
- Constants.SERVLET_PARAMETER_HEARTBEAT_RATE, "300"));
- } catch (NumberFormatException e) {
- getLogger().warning(
- Constants.WARNING_HEARTBEAT_INTERVAL_NOT_NUMERIC);
- heartbeatInterval = 300;
- }
- }
-
- private void checkIdleUICleanup() {
- idleRootCleanupEnabled = getApplicationOrSystemProperty(
- Constants.SERVLET_PARAMETER_CLOSE_IDLE_UIS, "false").equals(
- "true");
- }
-
- private Logger getLogger() {
- return Logger.getLogger(getClass().getName());
- }
}
diff --git a/server/src/com/vaadin/server/AbstractUIProvider.java b/server/src/com/vaadin/server/AbstractUIProvider.java
index 59ce31891d..ee8ebd2745 100644
--- a/server/src/com/vaadin/server/AbstractUIProvider.java
+++ b/server/src/com/vaadin/server/AbstractUIProvider.java
@@ -16,13 +16,18 @@
package com.vaadin.server;
-import com.vaadin.Application;
+import java.lang.annotation.Annotation;
+
+import com.vaadin.annotations.PreserveOnRefresh;
+import com.vaadin.annotations.Theme;
+import com.vaadin.annotations.Title;
+import com.vaadin.annotations.Widgetset;
import com.vaadin.ui.UI;
public abstract class AbstractUIProvider implements UIProvider {
@Override
- public UI createInstance(Application application, Class<? extends UI> type,
+ public UI createInstance(VaadinSession application, Class<? extends UI> type,
WrappedRequest request) {
try {
return type.newInstance();
@@ -32,4 +37,86 @@ public abstract class AbstractUIProvider implements UIProvider {
throw new RuntimeException("Could not access root class", e);
}
}
+
+ /**
+ * Helper to get an annotation for a class. If the annotation is not present
+ * on the target class, it's superclasses and implemented interfaces are
+ * also searched for the annotation.
+ *
+ * @param type
+ * the target class from which the annotation should be found
+ * @param annotationType
+ * the annotation type to look for
+ * @return an annotation of the given type, or <code>null</code> if the
+ * annotation is not present on the class
+ */
+ protected static <T extends Annotation> T getAnnotationFor(Class<?> type,
+ Class<T> annotationType) {
+ // Find from the class hierarchy
+ Class<?> currentType = type;
+ while (currentType != Object.class) {
+ T annotation = currentType.getAnnotation(annotationType);
+ if (annotation != null) {
+ return annotation;
+ } else {
+ currentType = currentType.getSuperclass();
+ }
+ }
+
+ // Find from an implemented interface
+ for (Class<?> iface : type.getInterfaces()) {
+ T annotation = iface.getAnnotation(annotationType);
+ if (annotation != null) {
+ return annotation;
+ }
+ }
+
+ return null;
+ }
+
+ @Override
+ public String getThemeForUI(WrappedRequest request,
+ Class<? extends UI> uiClass) {
+ Theme uiTheme = getAnnotationFor(uiClass, Theme.class);
+ if (uiTheme != null) {
+ return uiTheme.value();
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public String getWidgetsetForUI(WrappedRequest request,
+ Class<? extends UI> uiClass) {
+ Widgetset uiWidgetset = getAnnotationFor(uiClass, Widgetset.class);
+ if (uiWidgetset != null) {
+ return uiWidgetset.value();
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public boolean isUiPreserved(WrappedRequest request,
+ Class<? extends UI> uiClass) {
+ PreserveOnRefresh preserveOnRefresh = getAnnotationFor(uiClass,
+ PreserveOnRefresh.class);
+ return preserveOnRefresh != null;
+ }
+
+ @Override
+ public String getPageTitleForUI(WrappedRequest request,
+ Class<? extends UI> uiClass) {
+ Title titleAnnotation = getAnnotationFor(uiClass, Title.class);
+ if (titleAnnotation == null) {
+ return null;
+ } else {
+ return titleAnnotation.value();
+ }
+ }
+
+ @Override
+ public UI getExistingUI(WrappedRequest request) {
+ return null;
+ }
}
diff --git a/server/src/com/vaadin/server/AddonContext.java b/server/src/com/vaadin/server/AddonContext.java
index c9f2ac07eb..ca8c837a2e 100644
--- a/server/src/com/vaadin/server/AddonContext.java
+++ b/server/src/com/vaadin/server/AddonContext.java
@@ -22,7 +22,6 @@ import java.util.Iterator;
import java.util.List;
import java.util.ServiceLoader;
-import com.vaadin.Application;
import com.vaadin.event.EventRouter;
import com.vaadin.util.ReflectTools;
@@ -116,7 +115,7 @@ public class AddonContext {
* application.
*
* @see #addApplicationStartedListener(ApplicationStartedListener)
- * @see Application#addBootstrapListener(BootstrapListener)
+ * @see VaadinSession#addBootstrapListener(BootstrapListener)
*
* @param listener
* the bootstrap listener that should be added to all new
@@ -136,7 +135,7 @@ public class AddonContext {
* @param application
* the newly started application
*/
- public void fireApplicationStarted(Application application) {
+ public void fireApplicationStarted(VaadinSession application) {
eventRouter.fireEvent(new ApplicationStartedEvent(this, application));
for (BootstrapListener l : bootstrapListeners) {
application.addBootstrapListener(l);
@@ -144,9 +143,9 @@ public class AddonContext {
}
/**
- * Adds a listener that will be notified any time a new {@link Application}
+ * Adds a listener that will be notified any time a new {@link VaadinSession}
* instance is started or more precisely directly after
- * {@link Application#init()} has been invoked.
+ * {@link VaadinSession#init()} has been invoked.
*
* @param applicationStartListener
* the application start listener that should be added
diff --git a/server/src/com/vaadin/server/ApplicationConfiguration.java b/server/src/com/vaadin/server/ApplicationConfiguration.java
new file mode 100644
index 0000000000..edb33e6c39
--- /dev/null
+++ b/server/src/com/vaadin/server/ApplicationConfiguration.java
@@ -0,0 +1,99 @@
+/*
+ * 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.Properties;
+
+
+/**
+ * A collection of properties configured for all applications as well as a way
+ * of accessing third party properties not explicitely supported by this class.
+ *
+ * @author Vaadin Ltd
+ * @version @VERSION@
+ * @since 7.0.0
+ */
+public interface ApplicationConfiguration {
+ /**
+ * Returns whether Vaadin is in production mode.
+ *
+ * @return true if in production mode, false otherwise.
+ */
+ public boolean isProductionMode();
+
+ /**
+ * Returns whether cross-site request forgery protection is enabled.
+ *
+ * @return true if XSRF protection is enabled, false otherwise.
+ */
+ public boolean isXsrfProtectionEnabled();
+
+ /**
+ * Returns the time resources can be cached in the browsers, in seconds.
+ *
+ * @return The resource cache time.
+ */
+ public int getResourceCacheTime();
+
+ /**
+ * Returns the number of seconds between heartbeat requests of a UI, or a
+ * non-positive number if heartbeat is disabled.
+ *
+ * @return The time between heartbeats.
+ */
+ public int getHeartbeatInterval();
+
+ /**
+ * Returns whether UIs that have no other activity than heartbeat requests
+ * should be closed after they have been idle the maximum inactivity time
+ * enforced by the session.
+ *
+ * @see ApplicationContext#getMaxInactiveInterval()
+ *
+ * @since 7.0.0
+ *
+ * @return True if UIs receiving only heartbeat requests are eventually
+ * closed; false if heartbeat requests extend UI lifetime
+ * indefinitely.
+ */
+ public boolean isIdleUICleanupEnabled();
+
+ /**
+ * Gets the properties configured for the deployment, e.g. as init
+ * parameters to the servlet or portlet.
+ *
+ * @return properties for the application.
+ */
+ public Properties getInitParameters();
+
+ /**
+ * Gets a configured property. The properties are typically read from e.g.
+ * web.xml or from system properties of the JVM.
+ *
+ * @param propertyName
+ * The simple of the property, in some contexts, lookup might be
+ * performed using variations of the provided name.
+ * @param defaultValue
+ * the default value that should be used if no value has been
+ * defined
+ * @return the property value, or the passed default value if no property
+ * value is found
+ */
+ public String getApplicationOrSystemProperty(String propertyName,
+ String defaultValue);
+
+}
diff --git a/server/src/com/vaadin/server/ApplicationContext.java b/server/src/com/vaadin/server/ApplicationContext.java
deleted file mode 100644
index b698ea51c8..0000000000
--- a/server/src/com/vaadin/server/ApplicationContext.java
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- * 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.io.File;
-import java.io.PrintWriter;
-import java.io.Serializable;
-import java.io.StringWriter;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import javax.servlet.http.HttpSessionBindingEvent;
-import javax.servlet.http.HttpSessionBindingListener;
-
-import com.vaadin.Application;
-
-/**
- * <code>ApplicationContext</code> provides information about the running
- * context of the application. Each context is shared by all applications that
- * are open for one user. In a web-environment this corresponds to a
- * HttpSession.
- * <p>
- * Base class for web application contexts (including portlet contexts) that
- * handles the common tasks.
- *
- * @author Vaadin Ltd.
- * @since 3.1
- */
-public abstract class ApplicationContext implements HttpSessionBindingListener,
- Serializable {
-
- /**
- * Interface for listening to transaction events. Implement this interface
- * to listen to all transactions between the client and the application.
- *
- */
- public static interface TransactionListener extends Serializable {
-
- /**
- * Invoked at the beginning of every transaction.
- *
- * The transaction is linked to the context, not the application so if
- * you have multiple applications running in the same context you need
- * to check that the request is associated with the application you are
- * interested in. This can be done looking at the application parameter.
- *
- * @param application
- * the Application object.
- * @param transactionData
- * the Data identifying the transaction.
- */
- public void transactionStart(Application application,
- Object transactionData);
-
- /**
- * Invoked at the end of every transaction.
- *
- * The transaction is linked to the context, not the application so if
- * you have multiple applications running in the same context you need
- * to check that the request is associated with the application you are
- * interested in. This can be done looking at the application parameter.
- *
- * @param applcation
- * the Application object.
- * @param transactionData
- * the Data identifying the transaction.
- */
- public void transactionEnd(Application application,
- Object transactionData);
-
- }
-
- protected Collection<ApplicationContext.TransactionListener> listeners = Collections
- .synchronizedList(new LinkedList<ApplicationContext.TransactionListener>());
-
- protected final HashSet<Application> applications = new HashSet<Application>();
-
- protected WebBrowser browser = new WebBrowser();
-
- protected HashMap<Application, AbstractCommunicationManager> applicationToAjaxAppMgrMap = new HashMap<Application, AbstractCommunicationManager>();
-
- private long totalSessionTime = 0;
-
- private long lastRequestTime = -1;
-
- /**
- * Adds a transaction listener to this context. The transaction listener is
- * called before and after each each request related to this session except
- * when serving static resources.
- *
- * The transaction listener must not be null.
- *
- * @see com.vaadin.service.ApplicationContext#addTransactionListener(com.vaadin.service.ApplicationContext.TransactionListener)
- */
- public void addTransactionListener(
- ApplicationContext.TransactionListener listener) {
- if (listener != null) {
- listeners.add(listener);
- }
- }
-
- /**
- * Removes a transaction listener from this context.
- *
- * @param listener
- * the listener to be removed.
- * @see ApplicationContext.TransactionListener
- */
- public void removeTransactionListener(
- ApplicationContext.TransactionListener listener) {
- listeners.remove(listener);
- }
-
- /**
- * Sends a notification that a transaction is starting.
- *
- * @param application
- * The application associated with the transaction.
- * @param request
- * the HTTP or portlet request that triggered the transaction.
- */
- protected void startTransaction(Application application, Object request) {
- ArrayList<ApplicationContext.TransactionListener> currentListeners;
- synchronized (listeners) {
- currentListeners = new ArrayList<ApplicationContext.TransactionListener>(
- listeners);
- }
- for (ApplicationContext.TransactionListener listener : currentListeners) {
- listener.transactionStart(application, request);
- }
- }
-
- /**
- * Sends a notification that a transaction has ended.
- *
- * @param application
- * The application associated with the transaction.
- * @param request
- * the HTTP or portlet request that triggered the transaction.
- */
- protected void endTransaction(Application application, Object request) {
- LinkedList<Exception> exceptions = null;
-
- ArrayList<ApplicationContext.TransactionListener> currentListeners;
- synchronized (listeners) {
- currentListeners = new ArrayList<ApplicationContext.TransactionListener>(
- listeners);
- }
-
- for (ApplicationContext.TransactionListener listener : currentListeners) {
- try {
- listener.transactionEnd(application, request);
- } catch (final RuntimeException t) {
- if (exceptions == null) {
- exceptions = new LinkedList<Exception>();
- }
- exceptions.add(t);
- }
- }
-
- // If any runtime exceptions occurred, throw a combined exception
- if (exceptions != null) {
- final StringBuffer msg = new StringBuffer();
- for (Exception e : exceptions) {
- if (msg.length() == 0) {
- msg.append("\n\n--------------------------\n\n");
- }
- msg.append(e.getMessage() + "\n");
- final StringWriter trace = new StringWriter();
- e.printStackTrace(new PrintWriter(trace, true));
- msg.append(trace.toString());
- }
- throw new RuntimeException(msg.toString());
- }
- }
-
- /**
- * @see javax.servlet.http.HttpSessionBindingListener#valueBound(HttpSessionBindingEvent)
- */
- @Override
- public void valueBound(HttpSessionBindingEvent arg0) {
- // We are not interested in bindings
- }
-
- /**
- * @see javax.servlet.http.HttpSessionBindingListener#valueUnbound(HttpSessionBindingEvent)
- */
- @Override
- 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);
- }
- }
-
- /**
- * Get the web browser associated with this application context.
- *
- * Because application context is related to the http session and server
- * maintains one session per browser-instance, each context has exactly one
- * web browser associated with it.
- *
- * @return
- */
- public WebBrowser getBrowser() {
- return browser;
- }
-
- /**
- * Returns a collection of all the applications in this context.
- *
- * Each application context contains all active applications for one user.
- *
- * @return A collection containing all the applications in this context.
- */
- public Collection<Application> getApplications() {
- return Collections.unmodifiableCollection(applications);
- }
-
- protected void removeApplication(Application application) {
- applications.remove(application);
- applicationToAjaxAppMgrMap.remove(application);
- }
-
- /**
- * @return The total time spent servicing requests in this session.
- */
- public long getTotalSessionTime() {
- return totalSessionTime;
- }
-
- /**
- * Sets the time spent servicing the last request in the session and updates
- * the total time spent servicing requests in this session.
- *
- * @param time
- * the time spent in the last request.
- */
- public void setLastRequestTime(long time) {
- lastRequestTime = time;
- totalSessionTime += time;
- }
-
- /**
- * @return the time spent servicing the last request in this session.
- */
- public long getLastRequestTime() {
- return lastRequestTime;
- }
-
- private Logger getLogger() {
- return Logger.getLogger(ApplicationContext.class.getName());
- }
-
- /**
- * Returns application context base directory.
- *
- * Typically an application is deployed in a such way that is has an
- * application directory. For web applications this directory is the root
- * directory of the web applications. In some cases applications might not
- * have an application directory (for example web applications running
- * inside a war).
- *
- * @return The application base directory or null if the application has no
- * base directory.
- */
- public abstract File getBaseDirectory();
-
- /**
- * Returns the time between requests, in seconds, before this context is
- * invalidated. A negative time indicates the context should never timeout.
- */
- public abstract int getMaxInactiveInterval();
-
-} \ No newline at end of file
diff --git a/server/src/com/vaadin/server/ApplicationStartedEvent.java b/server/src/com/vaadin/server/ApplicationStartedEvent.java
index d06744ae40..9ecab4d477 100644
--- a/server/src/com/vaadin/server/ApplicationStartedEvent.java
+++ b/server/src/com/vaadin/server/ApplicationStartedEvent.java
@@ -18,7 +18,6 @@ package com.vaadin.server;
import java.util.EventObject;
-import com.vaadin.Application;
/**
* Event used by
@@ -29,7 +28,7 @@ import com.vaadin.Application;
* @since 7.0.0
*/
public class ApplicationStartedEvent extends EventObject {
- private final Application application;
+ private final VaadinSession application;
/**
* Creates a new event.
@@ -39,7 +38,7 @@ public class ApplicationStartedEvent extends EventObject {
* @param application
* the application that has been started
*/
- public ApplicationStartedEvent(AddonContext context, Application application) {
+ public ApplicationStartedEvent(AddonContext context, VaadinSession application) {
super(context);
this.application = application;
}
@@ -58,7 +57,7 @@ public class ApplicationStartedEvent extends EventObject {
*
* @return the newly created application
*/
- public Application getApplication() {
+ public VaadinSession getApplication() {
return application;
}
diff --git a/server/src/com/vaadin/server/ApplicationStartedListener.java b/server/src/com/vaadin/server/ApplicationStartedListener.java
index c54132d875..b7858447df 100644
--- a/server/src/com/vaadin/server/ApplicationStartedListener.java
+++ b/server/src/com/vaadin/server/ApplicationStartedListener.java
@@ -18,10 +18,9 @@ package com.vaadin.server;
import java.util.EventListener;
-import com.vaadin.Application;
/**
- * Listener that gets notified when a new {@link Application} has been started.
+ * Listener that gets notified when a new {@link VaadinSession} has been started.
* Add-ons can use this listener to automatically integrate with API tied to the
* Application API.
*
@@ -33,7 +32,7 @@ import com.vaadin.Application;
public interface ApplicationStartedListener extends EventListener {
/**
* Tells the listener that an application has been started (meaning that
- * {@link Application#init()} has been invoked.
+ * {@link VaadinSession#init()} has been invoked.
*
* @param event
* details about the event
diff --git a/server/src/com/vaadin/server/BootstrapFragmentResponse.java b/server/src/com/vaadin/server/BootstrapFragmentResponse.java
index 149f59e7a5..4b960263e7 100644
--- a/server/src/com/vaadin/server/BootstrapFragmentResponse.java
+++ b/server/src/com/vaadin/server/BootstrapFragmentResponse.java
@@ -20,7 +20,6 @@ import java.util.List;
import org.jsoup.nodes.Node;
-import com.vaadin.Application;
import com.vaadin.ui.UI;
/**
@@ -38,7 +37,7 @@ public class BootstrapFragmentResponse extends BootstrapResponse {
* Crate a new bootstrap fragment response.
*
* @see BootstrapResponse#BootstrapResponse(BootstrapHandler,
- * WrappedRequest, Application, Class)
+ * WrappedRequest, VaadinSession, Class)
*
* @param handler
* the bootstrap handler that is firing the event
@@ -55,7 +54,7 @@ public class BootstrapFragmentResponse extends BootstrapResponse {
* application HTML
*/
public BootstrapFragmentResponse(BootstrapHandler handler,
- WrappedRequest request, Application application,
+ WrappedRequest request, VaadinSession application,
Class<? extends UI> uiClass, List<Node> fragmentNodes) {
super(handler, request, application, uiClass);
this.fragmentNodes = fragmentNodes;
diff --git a/server/src/com/vaadin/server/BootstrapHandler.java b/server/src/com/vaadin/server/BootstrapHandler.java
index a1438312b6..6b8fb1952a 100644
--- a/server/src/com/vaadin/server/BootstrapHandler.java
+++ b/server/src/com/vaadin/server/BootstrapHandler.java
@@ -36,7 +36,6 @@ import org.jsoup.nodes.Element;
import org.jsoup.nodes.Node;
import org.jsoup.parser.Tag;
-import com.vaadin.Application;
import com.vaadin.external.json.JSONException;
import com.vaadin.external.json.JSONObject;
import com.vaadin.shared.ApplicationConstants;
@@ -68,7 +67,7 @@ public abstract class BootstrapHandler implements RequestHandler {
return bootstrapResponse.getRequest();
}
- public Application getApplication() {
+ public VaadinSession getApplication() {
return bootstrapResponse.getApplication();
}
@@ -104,7 +103,7 @@ public abstract class BootstrapHandler implements RequestHandler {
}
@Override
- public boolean handleRequest(Application application,
+ public boolean handleRequest(VaadinSession application,
WrappedRequest request, WrappedResponse response)
throws IOException {
@@ -218,8 +217,9 @@ public abstract class BootstrapHandler implements RequestHandler {
head.appendElement("meta").attr("http-equiv", "X-UA-Compatible")
.attr("content", "chrome=1");
- String title = context.getApplication().getPageTitleForUI(
- context.getRequest(), context.getUIClass());
+ String title = context.getApplication()
+ .getUiProvider(context.getRequest(), context.getUIClass())
+ .getPageTitleForUI(context.getRequest(), context.getUIClass());
if (title != null) {
head.appendElement("title").appendText(title);
}
@@ -245,7 +245,7 @@ public abstract class BootstrapHandler implements RequestHandler {
}
private BootstrapContext createContext(WrappedRequest request,
- WrappedResponse response, Application application,
+ WrappedResponse response, VaadinSession application,
Class<? extends UI> uiClass) {
BootstrapContext context = new BootstrapContext(response,
new BootstrapFragmentResponse(this, request, application,
@@ -270,8 +270,9 @@ public abstract class BootstrapHandler implements RequestHandler {
public String getWidgetsetForUI(BootstrapContext context) {
WrappedRequest request = context.getRequest();
- String widgetset = context.getApplication().getWidgetsetForUI(
- context.getRequest(), context.getUIClass());
+ String widgetset = context.getApplication()
+ .getUiProvider(context.getRequest(), context.getUIClass())
+ .getWidgetsetForUI(context.getRequest(), context.getUIClass());
if (widgetset == null) {
widgetset = request.getDeploymentConfiguration()
.getConfiguredWidgetset(request);
@@ -390,7 +391,7 @@ public abstract class BootstrapHandler implements RequestHandler {
protected JSONObject getApplicationParameters(BootstrapContext context)
throws JSONException, PaintException {
- Application application = context.getApplication();
+ VaadinSession application = context.getApplication();
JSONObject appConfig = new JSONObject();
@@ -419,7 +420,7 @@ public abstract class BootstrapHandler implements RequestHandler {
JSONObject defaults = new JSONObject();
WrappedRequest request = context.getRequest();
- Application application = context.getApplication();
+ VaadinSession application = context.getApplication();
DeploymentConfiguration deploymentConfiguration = request
.getDeploymentConfiguration();
@@ -461,8 +462,8 @@ public abstract class BootstrapHandler implements RequestHandler {
defaults.put("standalone", true);
}
- defaults.put("heartbeatInterval",
- deploymentConfiguration.getHeartbeatInterval());
+ defaults.put("heartbeatInterval", deploymentConfiguration
+ .getApplicationConfiguration().getHeartbeatInterval());
defaults.put("appUri", getAppUri(context));
@@ -497,8 +498,9 @@ public abstract class BootstrapHandler implements RequestHandler {
* @return
*/
public String getThemeName(BootstrapContext context) {
- return context.getApplication().getThemeForUI(context.getRequest(),
- context.getUIClass());
+ return context.getApplication()
+ .getUiProvider(context.getRequest(), context.getUIClass())
+ .getThemeForUI(context.getRequest(), context.getUIClass());
}
/**
diff --git a/server/src/com/vaadin/server/BootstrapPageResponse.java b/server/src/com/vaadin/server/BootstrapPageResponse.java
index a5fdfe4707..8f56042f8f 100644
--- a/server/src/com/vaadin/server/BootstrapPageResponse.java
+++ b/server/src/com/vaadin/server/BootstrapPageResponse.java
@@ -20,7 +20,6 @@ import java.util.Map;
import org.jsoup.nodes.Document;
-import com.vaadin.Application;
import com.vaadin.ui.UI;
/**
@@ -40,7 +39,7 @@ public class BootstrapPageResponse extends BootstrapResponse {
* Crate a new bootstrap page response.
*
* @see BootstrapResponse#BootstrapResponse(BootstrapHandler,
- * WrappedRequest, Application, Class)
+ * WrappedRequest, VaadinSession, Class)
*
* @param handler
* the bootstrap handler that is firing the event
@@ -58,7 +57,7 @@ public class BootstrapPageResponse extends BootstrapResponse {
* a map into which header data can be added
*/
public BootstrapPageResponse(BootstrapHandler handler,
- WrappedRequest request, Application application,
+ WrappedRequest request, VaadinSession application,
Class<? extends UI> uiClass, Document document,
Map<String, Object> headers) {
super(handler, request, application, uiClass);
diff --git a/server/src/com/vaadin/server/BootstrapResponse.java b/server/src/com/vaadin/server/BootstrapResponse.java
index 3173569059..b75544a87c 100644
--- a/server/src/com/vaadin/server/BootstrapResponse.java
+++ b/server/src/com/vaadin/server/BootstrapResponse.java
@@ -18,7 +18,6 @@ package com.vaadin.server;
import java.util.EventObject;
-import com.vaadin.Application;
import com.vaadin.ui.UI;
/**
@@ -30,7 +29,7 @@ import com.vaadin.ui.UI;
*/
public abstract class BootstrapResponse extends EventObject {
private final WrappedRequest request;
- private final Application application;
+ private final VaadinSession application;
private final Class<? extends UI> uiClass;
/**
@@ -48,7 +47,7 @@ public abstract class BootstrapResponse extends EventObject {
* the class of the UI that will be displayed on the page
*/
public BootstrapResponse(BootstrapHandler handler, WrappedRequest request,
- Application application, Class<? extends UI> uiClass) {
+ VaadinSession application, Class<? extends UI> uiClass) {
super(handler);
this.request = request;
this.application = application;
@@ -83,7 +82,7 @@ public abstract class BootstrapResponse extends EventObject {
*
* @return the application
*/
- public Application getApplication() {
+ public VaadinSession getApplication() {
return application;
}
diff --git a/server/src/com/vaadin/server/ClassResource.java b/server/src/com/vaadin/server/ClassResource.java
index 2f05115fd4..27643eda13 100644
--- a/server/src/com/vaadin/server/ClassResource.java
+++ b/server/src/com/vaadin/server/ClassResource.java
@@ -18,7 +18,6 @@ package com.vaadin.server;
import java.io.Serializable;
-import com.vaadin.Application;
import com.vaadin.service.FileTypeResolver;
import com.vaadin.ui.UI;
import com.vaadin.ui.UI.LegacyWindow;
@@ -115,7 +114,7 @@ public class ClassResource implements ConnectorResource, Serializable {
if (associatedClass == null) {
Class<? extends UI> associatedClass = UI.getCurrent().getClass();
if (associatedClass == LegacyWindow.class) {
- return Application.getCurrent().getClass();
+ return VaadinSession.getCurrent().getClass();
}
return associatedClass;
}
diff --git a/server/src/com/vaadin/server/CombinedRequest.java b/server/src/com/vaadin/server/CombinedRequest.java
index 0577c0098a..cc336ffa73 100644
--- a/server/src/com/vaadin/server/CombinedRequest.java
+++ b/server/src/com/vaadin/server/CombinedRequest.java
@@ -24,7 +24,6 @@ import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
-import com.vaadin.Application;
import com.vaadin.external.json.JSONArray;
import com.vaadin.external.json.JSONException;
import com.vaadin.external.json.JSONObject;
@@ -114,18 +113,8 @@ public class CombinedRequest implements WrappedRequest {
}
@Override
- public int getSessionMaxInactiveInterval() {
- return secondRequest.getSessionMaxInactiveInterval();
- }
-
- @Override
- public Object getSessionAttribute(String name) {
- return secondRequest.getSessionAttribute(name);
- }
-
- @Override
- public void setSessionAttribute(String name, Object attribute) {
- secondRequest.setSessionAttribute(name, attribute);
+ public WrappedSession getWrappedSession() {
+ return secondRequest.getWrappedSession();
}
@Override
@@ -153,9 +142,7 @@ public class CombinedRequest implements WrappedRequest {
@Override
public WebBrowser getWebBrowser() {
- ApplicationContext context = Application.getCurrent()
- .getContext();
- return context.getBrowser();
+ return VaadinSession.getCurrent().getBrowser();
}
};
}
diff --git a/server/src/com/vaadin/server/CommunicationManager.java b/server/src/com/vaadin/server/CommunicationManager.java
index cc92023919..32c4d2c217 100644
--- a/server/src/com/vaadin/server/CommunicationManager.java
+++ b/server/src/com/vaadin/server/CommunicationManager.java
@@ -21,7 +21,6 @@ import java.net.URL;
import javax.servlet.ServletContext;
-import com.vaadin.Application;
import com.vaadin.ui.UI;
/**
@@ -39,12 +38,12 @@ import com.vaadin.ui.UI;
public class CommunicationManager extends AbstractCommunicationManager {
/**
- * @deprecated use {@link #CommunicationManager(Application)} instead
+ * @deprecated use {@link #CommunicationManager(VaadinSession)} instead
* @param application
* @param applicationServlet
*/
@Deprecated
- public CommunicationManager(Application application,
+ public CommunicationManager(VaadinSession application,
VaadinServlet applicationServlet) {
super(application);
}
@@ -54,7 +53,7 @@ public class CommunicationManager extends AbstractCommunicationManager {
*
* @param application
*/
- public CommunicationManager(Application application) {
+ public CommunicationManager(VaadinSession application) {
super(application);
}
@@ -88,7 +87,7 @@ public class CommunicationManager extends AbstractCommunicationManager {
// don't use server and port in uri. It may cause problems with
// some
// virtual server configurations which lose the server name
- Application application = context.getApplication();
+ VaadinSession application = context.getApplication();
URL url = application.getURL();
String appUrl = url.getPath();
if (appUrl.endsWith("/")) {
@@ -112,8 +111,8 @@ public class CommunicationManager extends AbstractCommunicationManager {
@Override
protected InputStream getThemeResourceAsStream(UI uI, String themeName,
String resource) {
- ServletApplicationContext context = (ServletApplicationContext) uI
- .getApplication().getContext();
+ VaadinServletSession context = (VaadinServletSession) uI
+ .getSession();
ServletContext servletContext = context.getHttpSession()
.getServletContext();
return servletContext.getResourceAsStream("/"
diff --git a/server/src/com/vaadin/server/ConnectorResourceHandler.java b/server/src/com/vaadin/server/ConnectorResourceHandler.java
index b988510b8e..6702fb140f 100644
--- a/server/src/com/vaadin/server/ConnectorResourceHandler.java
+++ b/server/src/com/vaadin/server/ConnectorResourceHandler.java
@@ -8,7 +8,6 @@ import java.util.regex.Pattern;
import javax.servlet.http.HttpServletResponse;
-import com.vaadin.Application;
import com.vaadin.shared.ApplicationConstants;
import com.vaadin.ui.UI;
@@ -25,7 +24,7 @@ public class ConnectorResourceHandler implements RequestHandler {
}
@Override
- public boolean handleRequest(Application application,
+ public boolean handleRequest(VaadinSession application,
WrappedRequest request, WrappedResponse response)
throws IOException {
String requestPath = request.getRequestPathInfo();
@@ -45,7 +44,7 @@ public class ConnectorResourceHandler implements RequestHandler {
}
UI.setCurrent(ui);
- Application.setCurrent(ui.getApplication());
+ VaadinSession.setCurrent(ui.getSession());
ClientConnector connector = ui.getConnectorTracker().getConnector(
cid);
diff --git a/server/src/com/vaadin/server/DefaultUIProvider.java b/server/src/com/vaadin/server/DefaultUIProvider.java
index 93128aad28..9babf4704e 100644
--- a/server/src/com/vaadin/server/DefaultUIProvider.java
+++ b/server/src/com/vaadin/server/DefaultUIProvider.java
@@ -16,16 +16,15 @@
package com.vaadin.server;
-import com.vaadin.Application;
import com.vaadin.ui.UI;
public class DefaultUIProvider extends AbstractUIProvider {
@Override
- public Class<? extends UI> getUIClass(Application application,
+ public Class<? extends UI> getUIClass(VaadinSession application,
WrappedRequest request) {
- Object uiClassNameObj = application
- .getProperty(Application.UI_PARAMETER);
+ Object uiClassNameObj = application.getConfiguration()
+ .getInitParameters().getProperty(VaadinSession.UI_PARAMETER);
if (uiClassNameObj instanceof String) {
String uiClassName = uiClassNameObj.toString();
diff --git a/server/src/com/vaadin/server/DeploymentConfiguration.java b/server/src/com/vaadin/server/DeploymentConfiguration.java
index 6150edbafb..0a70ef09b3 100644
--- a/server/src/com/vaadin/server/DeploymentConfiguration.java
+++ b/server/src/com/vaadin/server/DeploymentConfiguration.java
@@ -16,9 +16,9 @@
package com.vaadin.server;
+import java.io.File;
import java.io.Serializable;
import java.util.Iterator;
-import java.util.Properties;
import javax.portlet.PortletContext;
import javax.servlet.ServletContext;
@@ -82,22 +82,6 @@ public interface DeploymentConfiguration extends Serializable {
public boolean isStandalone(WrappedRequest request);
/**
- * Gets a configured property. The properties are typically read from e.g.
- * web.xml or from system properties of the JVM.
- *
- * @param propertyName
- * The simple of the property, in some contexts, lookup might be
- * performed using variations of the provided name.
- * @param defaultValue
- * the default value that should be used if no value has been
- * defined
- * @return the property value, or the passed default value if no property
- * value is found
- */
- public String getApplicationOrSystemProperty(String propertyName,
- String defaultValue);
-
- /**
* Get the class loader to use for loading classes loaded by name, e.g.
* custom UI classes. <code>null</code> indicates that the default class
* loader should be used.
@@ -122,12 +106,11 @@ public interface DeploymentConfiguration extends Serializable {
public String getMimeType(String resourceName);
/**
- * Gets the properties configured for the deployment, e.g. as init
- * parameters to the servlet or portlet.
+ * Gets the application configuration.
*
- * @return properties for the application.
+ * @return the application configuration
*/
- public Properties getInitParameters();
+ public ApplicationConfiguration getApplicationConfiguration();
public Iterator<AddonContextListener> getAddonContextListeners();
@@ -136,61 +119,23 @@ public interface DeploymentConfiguration extends Serializable {
public void setAddonContext(AddonContext vaadinContext);
/**
- * Returns whether Vaadin is in production mode.
- *
- * @since 7.0.0
- *
- * @return true if in production mode, false otherwise.
- */
- public boolean isProductionMode();
-
- /**
- * Returns whether cross-site request forgery protection is enabled.
- *
- * @since 7.0.0
- *
- * @return true if XSRF protection is enabled, false otherwise.
- */
- public boolean isXsrfProtectionEnabled();
-
- /**
- * Returns the time resources can be cached in the browsers, in seconds.
- *
- * @since 7.0.0
- *
- * @return The resource cache time.
- */
- public int getResourceCacheTime();
-
- /**
- * Returns the number of seconds between heartbeat requests of a UI, or a
- * non-positive number if heartbeat is disabled.
- *
- * @since 7.0.0
+ * Gets the system messages object
*
- * @return The time between heartbeats.
+ * @return the system messages object
*/
- public int getHeartbeatInterval();
+ public SystemMessages getSystemMessages();
/**
- * Returns whether UIs that have no other activity than heartbeat requests
- * should be closed after they have been idle the maximum inactivity time
- * enforced by the session.
- *
- * @see ApplicationContext#getMaxInactiveInterval()
+ * Returns application context base directory.
*
- * @since 7.0.0
+ * Typically an application is deployed in a such way that is has an
+ * application directory. For web applications this directory is the root
+ * directory of the web applications. In some cases applications might not
+ * have an application directory (for example web applications running
+ * inside a war).
*
- * @return True if UIs receiving only heartbeat requests are eventually
- * closed; false if heartbeat requests extend UI lifetime
- * indefinitely.
+ * @return The application base directory or null if the application has no
+ * base directory.
*/
- public boolean isIdleUICleanupEnabled();
-
- /**
- * Gets the system messages object
- *
- * @return the system messages object
- */
- public SystemMessages getSystemMessages();
+ public File getBaseDirectory();
}
diff --git a/server/src/com/vaadin/server/FileResource.java b/server/src/com/vaadin/server/FileResource.java
index fbf353362e..2dd5b7f589 100644
--- a/server/src/com/vaadin/server/FileResource.java
+++ b/server/src/com/vaadin/server/FileResource.java
@@ -20,7 +20,6 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
-import com.vaadin.Application;
import com.vaadin.server.Terminal.ErrorEvent;
import com.vaadin.service.FileTypeResolver;
@@ -74,7 +73,7 @@ public class FileResource implements ConnectorResource {
return ds;
} catch (final FileNotFoundException e) {
// Log the exception using the application error handler
- Application.getCurrent().getErrorHandler()
+ VaadinSession.getCurrent().getErrorHandler()
.terminalError(new ErrorEvent() {
@Override
diff --git a/server/src/com/vaadin/server/GAEVaadinServlet.java b/server/src/com/vaadin/server/GAEVaadinServlet.java
index 642737f73b..4ea1dff7f4 100644
--- a/server/src/com/vaadin/server/GAEVaadinServlet.java
+++ b/server/src/com/vaadin/server/GAEVaadinServlet.java
@@ -241,7 +241,7 @@ public class GAEVaadinServlet extends VaadinServlet {
}
// de-serialize or create application context, store in session
- ApplicationContext ctx = getApplicationContext(request, memcache);
+ VaadinSession ctx = getApplicationContext(request, memcache);
super.service(request, response);
@@ -291,8 +291,8 @@ public class GAEVaadinServlet extends VaadinServlet {
}
}
- protected ApplicationContext getApplicationContext(
- HttpServletRequest request, MemcacheService memcache) {
+ protected VaadinSession getApplicationContext(HttpServletRequest request,
+ MemcacheService memcache) {
HttpSession session = request.getSession();
String id = AC_BASE + session.getId();
byte[] serializedAC = (byte[]) memcache.get(id);
@@ -320,10 +320,9 @@ public class GAEVaadinServlet extends VaadinServlet {
ObjectInputStream ois;
try {
ois = new ObjectInputStream(bais);
- ApplicationContext applicationContext = (ApplicationContext) ois
- .readObject();
- session.setAttribute(ServletApplicationContext.class.getName(),
- applicationContext);
+ VaadinSession applicationContext = (VaadinSession) ois.readObject();
+ applicationContext.storeInSession(new WrappedHttpSession(
+ session));
} catch (IOException e) {
getLogger().log(
Level.WARNING,
@@ -360,7 +359,7 @@ public class GAEVaadinServlet extends VaadinServlet {
private void cleanSession(HttpServletRequest request) {
HttpSession session = request.getSession(false);
if (session != null) {
- session.removeAttribute(ServletApplicationContext.class.getName());
+ session.removeAttribute(VaadinServletSession.class.getName());
}
}
diff --git a/server/src/com/vaadin/server/GlobalResourceHandler.java b/server/src/com/vaadin/server/GlobalResourceHandler.java
index 441d884f58..03dab9817d 100644
--- a/server/src/com/vaadin/server/GlobalResourceHandler.java
+++ b/server/src/com/vaadin/server/GlobalResourceHandler.java
@@ -28,7 +28,6 @@ import java.util.regex.Pattern;
import javax.servlet.http.HttpServletResponse;
-import com.vaadin.Application;
import com.vaadin.shared.ApplicationConstants;
import com.vaadin.ui.UI;
@@ -66,7 +65,7 @@ public class GlobalResourceHandler implements RequestHandler {
"");
@Override
- public boolean handleRequest(Application application,
+ public boolean handleRequest(VaadinSession application,
WrappedRequest request, WrappedResponse response)
throws IOException {
String pathInfo = request.getRequestPathInfo();
diff --git a/server/src/com/vaadin/server/HttpServletRequestListener.java b/server/src/com/vaadin/server/HttpServletRequestListener.java
deleted file mode 100644
index e871dca05d..0000000000
--- a/server/src/com/vaadin/server/HttpServletRequestListener.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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.io.Serializable;
-
-import javax.servlet.Filter;
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import com.vaadin.Application;
-
-/**
- * {@link Application} that implements this interface gets notified of request
- * start and end by terminal.
- * <p>
- * Interface can be used for several helper tasks including:
- * <ul>
- * <li>Opening and closing database connections
- * <li>Implementing {@link ThreadLocal}
- * <li>Setting/Getting {@link Cookie}
- * </ul>
- * <p>
- * Alternatives for implementing similar features are are Servlet {@link Filter}
- * s and {@link ApplicationContext.TransactionListener}s in Vaadin.
- *
- * @since 6.2
- * @see PortletRequestListener
- */
-public interface HttpServletRequestListener extends Serializable {
-
- /**
- * This method is called before {@link Terminal} applies the request to
- * Application.
- *
- * @param request
- * @param response
- */
- public void onRequestStart(HttpServletRequest request,
- HttpServletResponse response);
-
- /**
- * This method is called at the end of each request.
- *
- * @param request
- * @param response
- */
- public void onRequestEnd(HttpServletRequest request,
- HttpServletResponse response);
-} \ No newline at end of file
diff --git a/server/src/com/vaadin/server/JsonPaintTarget.java b/server/src/com/vaadin/server/JsonPaintTarget.java
index b193c47528..d2f90c33b6 100644
--- a/server/src/com/vaadin/server/JsonPaintTarget.java
+++ b/server/src/com/vaadin/server/JsonPaintTarget.java
@@ -345,7 +345,7 @@ public class JsonPaintTarget implements PaintTarget {
throw new NullPointerException();
}
ClientConnector ownerConnector = openPaintables.peek();
- ownerConnector.getUI().getApplication().getGlobalResourceHandler(true)
+ ownerConnector.getUI().getSession().getGlobalResourceHandler(true)
.register(value, ownerConnector);
ResourceReference reference = ResourceReference.create(value,
diff --git a/server/src/com/vaadin/server/LegacyVaadinPortlet.java b/server/src/com/vaadin/server/LegacyVaadinPortlet.java
new file mode 100644
index 0000000000..f436cbb624
--- /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.server.ServletPortletHelper.ApplicationClassException;
+
+public class LegacyVaadinPortlet extends VaadinPortlet {
+
+ protected Class<? extends Application> getApplicationClass()
+ throws ClassNotFoundException {
+ try {
+ return ServletPortletHelper
+ .getLegacyApplicationClass(getDeploymentConfiguration());
+ } catch (ApplicationClassException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ protected Application getNewApplication(PortletRequest request)
+ throws PortletException {
+ try {
+ Class<? extends Application> applicationClass = getApplicationClass();
+ return applicationClass.newInstance();
+ } catch (Exception e) {
+ throw new PortletException(e);
+ }
+ }
+
+ @Override
+ protected VaadinPortletSession createApplication(
+ PortletRequest request) throws PortletException {
+ VaadinPortletSession application = super
+ .createApplication(request);
+
+ // Must set current before running init()
+ VaadinSession.setCurrent(application);
+
+ Application 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..93a9410509
--- /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.server.ServletPortletHelper.ApplicationClassException;
+
+public class LegacyVaadinServlet extends VaadinServlet {
+
+ protected Class<? extends Application> getApplicationClass()
+ throws ClassNotFoundException {
+ try {
+ return ServletPortletHelper
+ .getLegacyApplicationClass(getDeploymentConfiguration());
+ } catch (ApplicationClassException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ protected Application getNewApplication(HttpServletRequest request)
+ throws ServletException {
+ try {
+ Class<? extends Application> applicationClass = getApplicationClass();
+ return applicationClass.newInstance();
+ } catch (Exception e) {
+ throw new ServletException(e);
+ }
+ }
+
+ @Override
+ protected VaadinServletSession createApplication(
+ HttpServletRequest request) throws ServletException {
+ VaadinServletSession application = super
+ .createApplication(request);
+
+ // Must set current before running init()
+ VaadinSession.setCurrent(application);
+
+ Application legacyApplication = getNewApplication(request);
+ legacyApplication.doInit();
+ application.addUIProvider(legacyApplication);
+
+ return application;
+ }
+
+}
diff --git a/server/src/com/vaadin/server/Page.java b/server/src/com/vaadin/server/Page.java
index 015c6c907f..9a0948edc8 100644
--- a/server/src/com/vaadin/server/Page.java
+++ b/server/src/com/vaadin/server/Page.java
@@ -391,7 +391,7 @@ public class Page implements Serializable {
}
public WebBrowser getWebBrowser() {
- return uI.getApplication().getContext().getBrowser();
+ return uI.getSession().getBrowser();
}
public void setBrowserWindowSize(int width, int height) {
diff --git a/server/src/com/vaadin/server/PortletCommunicationManager.java b/server/src/com/vaadin/server/PortletCommunicationManager.java
index cb3a8eab80..1a2b892a32 100644
--- a/server/src/com/vaadin/server/PortletCommunicationManager.java
+++ b/server/src/com/vaadin/server/PortletCommunicationManager.java
@@ -26,7 +26,6 @@ import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import javax.portlet.ResourceURL;
-import com.vaadin.Application;
import com.vaadin.external.json.JSONException;
import com.vaadin.external.json.JSONObject;
import com.vaadin.shared.ApplicationConstants;
@@ -41,7 +40,7 @@ import com.vaadin.ui.UI;
@SuppressWarnings("serial")
public class PortletCommunicationManager extends AbstractCommunicationManager {
- public PortletCommunicationManager(Application application) {
+ public PortletCommunicationManager(VaadinSession application) {
super(application);
}
@@ -49,7 +48,7 @@ public class PortletCommunicationManager extends AbstractCommunicationManager {
protected BootstrapHandler createBootstrapHandler() {
return new BootstrapHandler() {
@Override
- public boolean handleRequest(Application application,
+ public boolean handleRequest(VaadinSession application,
WrappedRequest request, WrappedResponse response)
throws IOException {
PortletRequest portletRequest = WrappedPortletRequest.cast(
@@ -130,8 +129,9 @@ public class PortletCommunicationManager extends AbstractCommunicationManager {
protected String getMainDivStyle(BootstrapContext context) {
DeploymentConfiguration deploymentConfiguration = context
.getRequest().getDeploymentConfiguration();
- return deploymentConfiguration.getApplicationOrSystemProperty(
- VaadinPortlet.PORTLET_PARAMETER_STYLE, null);
+ return deploymentConfiguration.getApplicationConfiguration()
+ .getApplicationOrSystemProperty(
+ VaadinPortlet.PORTLET_PARAMETER_STYLE, null);
}
@Override
@@ -156,8 +156,8 @@ public class PortletCommunicationManager extends AbstractCommunicationManager {
@Override
protected InputStream getThemeResourceAsStream(UI uI, String themeName,
String resource) {
- PortletApplicationContext2 context = (PortletApplicationContext2) uI
- .getApplication().getContext();
+ VaadinPortletSession context = (VaadinPortletSession) uI
+ .getSession();
PortletContext portletContext = context.getPortletSession()
.getPortletContext();
return portletContext.getResourceAsStream("/"
diff --git a/server/src/com/vaadin/server/PortletRequestListener.java b/server/src/com/vaadin/server/PortletRequestListener.java
deleted file mode 100644
index 4562ddf7b9..0000000000
--- a/server/src/com/vaadin/server/PortletRequestListener.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * 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.io.Serializable;
-
-import javax.portlet.PortletRequest;
-import javax.portlet.PortletResponse;
-import javax.servlet.Filter;
-
-import com.vaadin.Application;
-
-/**
- * An {@link Application} that implements this interface gets notified of
- * request start and end by the terminal. It is quite similar to the
- * {@link HttpServletRequestListener}, but the parameters are Portlet specific.
- * If an Application is deployed as both a Servlet and a Portlet, one most
- * likely needs to implement both.
- * <p>
- * Only JSR 286 style Portlets are supported.
- * <p>
- * The interface can be used for several helper tasks including:
- * <ul>
- * <li>Opening and closing database connections
- * <li>Implementing {@link ThreadLocal}
- * <li>Inter-portlet communication
- * </ul>
- * <p>
- * Alternatives for implementing similar features are are Servlet {@link Filter}
- * s and {@link ApplicationContext.TransactionListener}s in Vaadin.
- *
- * @since 6.2
- * @see HttpServletRequestListener
- */
-public interface PortletRequestListener extends Serializable {
-
- /**
- * This method is called before {@link Terminal} applies the request to
- * Application.
- *
- * @param requestData
- * the {@link PortletRequest} about to change Application state
- */
- public void onRequestStart(PortletRequest request, PortletResponse response);
-
- /**
- * This method is called at the end of each request.
- *
- * @param requestData
- * the {@link PortletRequest}
- */
- public void onRequestEnd(PortletRequest request, PortletResponse response);
-} \ No newline at end of file
diff --git a/server/src/com/vaadin/server/RequestHandler.java b/server/src/com/vaadin/server/RequestHandler.java
index fcc506cc54..0557c06378 100644
--- a/server/src/com/vaadin/server/RequestHandler.java
+++ b/server/src/com/vaadin/server/RequestHandler.java
@@ -19,11 +19,10 @@ package com.vaadin.server;
import java.io.IOException;
import java.io.Serializable;
-import com.vaadin.Application;
/**
* Handler for producing a response to non-UIDL requests. Handlers can be added
- * to applications using {@link Application#addRequestHandler(RequestHandler)}
+ * to applications using {@link VaadinSession#addRequestHandler(RequestHandler)}
*/
public interface RequestHandler extends Serializable {
@@ -42,7 +41,7 @@ public interface RequestHandler extends Serializable {
* handlers should be called, otherwise false
* @throws IOException
*/
- boolean handleRequest(Application application, WrappedRequest request,
+ boolean handleRequest(VaadinSession application, WrappedRequest request,
WrappedResponse response) throws IOException;
}
diff --git a/server/src/com/vaadin/server/RequestTimer.java b/server/src/com/vaadin/server/RequestTimer.java
index 470677e331..149a1499e7 100644
--- a/server/src/com/vaadin/server/RequestTimer.java
+++ b/server/src/com/vaadin/server/RequestTimer.java
@@ -44,7 +44,7 @@ public class RequestTimer implements Serializable {
*
* @param context
*/
- public void stop(ApplicationContext context) {
+ public void stop(VaadinSession context) {
// Measure and store the total handling time. This data can be
// used in TestBench 3 tests.
long time = (System.nanoTime() - requestStartTime) / 1000000;
diff --git a/server/src/com/vaadin/server/ResourceReference.java b/server/src/com/vaadin/server/ResourceReference.java
index 098fb6c3e4..815cbee275 100644
--- a/server/src/com/vaadin/server/ResourceReference.java
+++ b/server/src/com/vaadin/server/ResourceReference.java
@@ -71,7 +71,7 @@ public class ResourceReference extends URLReference {
ConnectorResource connectorResource = (ConnectorResource) resource;
GlobalResourceHandler globalResourceHandler = connector.getUI()
- .getApplication().getGlobalResourceHandler(false);
+ .getSession().getGlobalResourceHandler(false);
if (globalResourceHandler != null) {
String uri = globalResourceHandler.getUri(connector,
connectorResource);
diff --git a/server/src/com/vaadin/server/RestrictedRenderResponse.java b/server/src/com/vaadin/server/RestrictedRenderResponse.java
index 6923a042d6..206c5f349c 100644
--- a/server/src/com/vaadin/server/RestrictedRenderResponse.java
+++ b/server/src/com/vaadin/server/RestrictedRenderResponse.java
@@ -36,7 +36,7 @@ import org.w3c.dom.Element;
* Read-only wrapper for a {@link RenderResponse}.
*
* Only for use by {@link PortletApplicationContext} and
- * {@link PortletApplicationContext2}.
+ * {@link VaadinPortletSession}.
*/
class RestrictedRenderResponse implements RenderResponse, Serializable {
diff --git a/server/src/com/vaadin/server/ServletApplicationContext.java b/server/src/com/vaadin/server/ServletApplicationContext.java
deleted file mode 100644
index a38c523254..0000000000
--- a/server/src/com/vaadin/server/ServletApplicationContext.java
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * 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.io.File;
-import java.util.Enumeration;
-import java.util.HashMap;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpSession;
-import javax.servlet.http.HttpSessionBindingEvent;
-import javax.servlet.http.HttpSessionBindingListener;
-
-import com.vaadin.Application;
-
-/**
- * Web application context for Vaadin applications.
- *
- * This is automatically added as a {@link HttpSessionBindingListener} when
- * added to a {@link HttpSession}.
- *
- * @author Vaadin Ltd.
- * @since 3.1
- */
-@SuppressWarnings("serial")
-public class ServletApplicationContext extends ApplicationContext {
-
- protected transient HttpSession session;
- private transient boolean reinitializingSession = false;
-
- /**
- * Stores a reference to the currentRequest. Null it not inside a request.
- */
- private transient Object currentRequest = null;
-
- /**
- * Creates a new Web Application Context.
- *
- */
- protected ServletApplicationContext() {
-
- }
-
- @Override
- protected void startTransaction(Application application, Object request) {
- currentRequest = request;
- super.startTransaction(application, request);
- }
-
- @Override
- protected void endTransaction(Application application, Object request) {
- super.endTransaction(application, request);
- currentRequest = null;
- }
-
- @Override
- public void valueUnbound(HttpSessionBindingEvent event) {
- if (!reinitializingSession) {
- // Avoid closing the application if we are only reinitializing the
- // session. Closing the application would cause the state to be lost
- // and a new application to be created, which is not what we want.
- super.valueUnbound(event);
- }
- }
-
- /**
- * Discards the current session and creates a new session with the same
- * contents. The purpose of this is to introduce a new session key in order
- * to avoid session fixation attacks.
- */
- @SuppressWarnings("unchecked")
- public void reinitializeSession() {
-
- HttpSession oldSession = getHttpSession();
-
- // Stores all attributes (security key, reference to this context
- // instance) so they can be added to the new session
- HashMap<String, Object> attrs = new HashMap<String, Object>();
- for (Enumeration<String> e = oldSession.getAttributeNames(); e
- .hasMoreElements();) {
- String name = e.nextElement();
- attrs.put(name, oldSession.getAttribute(name));
- }
-
- // Invalidate the current session, set flag to avoid call to
- // valueUnbound
- reinitializingSession = true;
- oldSession.invalidate();
- reinitializingSession = false;
-
- // Create a new session
- HttpSession newSession = ((HttpServletRequest) currentRequest)
- .getSession();
-
- // Restores all attributes (security key, reference to this context
- // instance)
- for (String name : attrs.keySet()) {
- newSession.setAttribute(name, attrs.get(name));
- }
-
- // Update the "current session" variable
- session = newSession;
- }
-
- /**
- * Gets the application context base directory.
- *
- * @see com.vaadin.server.ApplicationContext#getBaseDirectory()
- */
- @Override
- public File getBaseDirectory() {
- final String realPath = VaadinServlet.getResourcePath(
- session.getServletContext(), "/");
- if (realPath == null) {
- return null;
- }
- return new File(realPath);
- }
-
- /**
- * Gets the http-session application is running in.
- *
- * @return HttpSession this application context resides in.
- */
- public HttpSession getHttpSession() {
- return session;
- }
-
- /**
- * Gets the application context for an HttpSession.
- *
- * @param session
- * the HTTP session.
- * @return the application context for HttpSession.
- */
- static public ServletApplicationContext getApplicationContext(
- HttpSession session) {
- ServletApplicationContext cx = (ServletApplicationContext) session
- .getAttribute(ServletApplicationContext.class.getName());
- if (cx == null) {
- cx = new ServletApplicationContext();
- session.setAttribute(ServletApplicationContext.class.getName(), cx);
- }
- if (cx.session == null) {
- cx.session = 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;
- }
-
- @Override
- public int getMaxInactiveInterval() {
- return getHttpSession().getMaxInactiveInterval();
- }
-}
diff --git a/server/src/com/vaadin/server/ServletPortletHelper.java b/server/src/com/vaadin/server/ServletPortletHelper.java
index f9ca55b50e..609168ee96 100644
--- a/server/src/com/vaadin/server/ServletPortletHelper.java
+++ b/server/src/com/vaadin/server/ServletPortletHelper.java
@@ -1,6 +1,7 @@
package com.vaadin.server;
import java.io.Serializable;
+import java.util.Properties;
import com.vaadin.Application;
import com.vaadin.shared.ApplicationConstants;
@@ -40,27 +41,22 @@ class ServletPortletHelper implements Serializable {
}
}
- static Class<? extends Application> getApplicationClass(
+ static Class<? extends Application> getLegacyApplicationClass(
DeploymentConfiguration deploymentConfiguration)
throws ApplicationClassException {
- String applicationParameter = deploymentConfiguration
- .getInitParameters().getProperty("application");
- String uiParameter = deploymentConfiguration.getInitParameters()
- .getProperty(Application.UI_PARAMETER);
+ Properties initParameters = deploymentConfiguration
+ .getApplicationConfiguration().getInitParameters();
+ String applicationParameter = initParameters.getProperty("application");
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(
+ Application.class);
} catch (final ClassNotFoundException e) {
throw new ApplicationClassException(
"Failed to load application class: " + applicationParameter,
@@ -71,7 +67,7 @@ class ServletPortletHelper implements Serializable {
private static void verifyUIClass(String className, ClassLoader classLoader)
throws ApplicationClassException {
if (className == null) {
- throw new ApplicationClassException(Application.UI_PARAMETER
+ throw new ApplicationClassException(VaadinSession.UI_PARAMETER
+ " init parameter not defined");
}
@@ -136,4 +132,25 @@ class ServletPortletHelper implements Serializable {
ApplicationConstants.HEARTBEAT_REQUEST_PATH);
}
+ public static void initDefaultUIProvider(VaadinSession application,
+ DeploymentConfiguration deploymentConfiguration)
+ throws ApplicationClassException {
+ String uiProperty = deploymentConfiguration
+ .getApplicationConfiguration().getInitParameters()
+ .getProperty(VaadinSession.UI_PARAMETER);
+ if (uiProperty != null) {
+ verifyUIClass(uiProperty, deploymentConfiguration.getClassLoader());
+ application.addUIProvider(new DefaultUIProvider());
+ }
+ }
+
+ public static void checkUiProviders(VaadinSession newApplication)
+ throws ApplicationClassException {
+ if (newApplication.getUIProviders().isEmpty()) {
+ throw new ApplicationClassException(
+ "No UIProvider has been added to the application and there is no \""
+ + VaadinSession.UI_PARAMETER + "\" init parameter.");
+ }
+ }
+
}
diff --git a/server/src/com/vaadin/server/StreamVariable.java b/server/src/com/vaadin/server/StreamVariable.java
index f289e7612a..a75cc2f0d7 100644
--- a/server/src/com/vaadin/server/StreamVariable.java
+++ b/server/src/com/vaadin/server/StreamVariable.java
@@ -18,7 +18,6 @@ package com.vaadin.server;
import java.io.OutputStream;
import java.io.Serializable;
-import com.vaadin.Application;
import com.vaadin.server.StreamVariable.StreamingEndEvent;
import com.vaadin.server.StreamVariable.StreamingErrorEvent;
import com.vaadin.server.StreamVariable.StreamingStartEvent;
@@ -152,7 +151,7 @@ public interface StreamVariable extends Serializable {
* the streaming ended before the end of the input. The streaming may fail
* due an interruption by {@link } or due an other unknown exception in
* communication. In the latter case the exception is also passed to
- * {@link Application#terminalError(com.vaadin.server.Terminal.ErrorEvent)}
+ * {@link VaadinSession#terminalError(com.vaadin.server.Terminal.ErrorEvent)}
* .
*/
public interface StreamingErrorEvent extends StreamingEvent {
diff --git a/server/src/com/vaadin/server/SystemMessages.java b/server/src/com/vaadin/server/SystemMessages.java
index 17aed0003e..3f6a0f9a68 100644
--- a/server/src/com/vaadin/server/SystemMessages.java
+++ b/server/src/com/vaadin/server/SystemMessages.java
@@ -18,7 +18,6 @@ package com.vaadin.server;
import java.io.Serializable;
-import com.vaadin.Application;
/**
@@ -26,7 +25,7 @@ import com.vaadin.Application;
* critical situations that can occur.
* <p>
* Customize by overriding the static
- * {@link Application#getSystemMessages()} and returning
+ * {@link VaadinSession#getSystemMessages()} and returning
* {@link CustomizedSystemMessages}.
* </p>
* <p>
diff --git a/server/src/com/vaadin/server/UIProvider.java b/server/src/com/vaadin/server/UIProvider.java
index ea73a705ea..b2908a04d6 100644
--- a/server/src/com/vaadin/server/UIProvider.java
+++ b/server/src/com/vaadin/server/UIProvider.java
@@ -16,13 +16,84 @@
package com.vaadin.server;
-import com.vaadin.Application;
+import com.vaadin.annotations.Widgetset;
import com.vaadin.ui.UI;
public interface UIProvider {
- public Class<? extends UI> getUIClass(Application application,
+ public Class<? extends UI> getUIClass(VaadinSession application,
WrappedRequest request);
- public UI createInstance(Application application, Class<? extends UI> type,
+ public UI createInstance(VaadinSession application, Class<? extends UI> type,
WrappedRequest request);
+
+ public String getPageTitleForUI(WrappedRequest request,
+ Class<? extends UI> uiClass);
+
+ /**
+ * Checks whether the same UI state should be reused if the framework can
+ * detect that the application is opened in a browser window where it has
+ * previously been open. The framework attempts to discover this by checking
+ * the value of window.name in the browser.
+ *
+ * @param request
+ * @param uiClass
+ *
+ * @return <code>true</code>if the same UI instance should be reused e.g.
+ * when the browser window is refreshed.
+ */
+ public boolean isUiPreserved(WrappedRequest request,
+ Class<? extends UI> uiClass);
+
+ /**
+ * Finds the widgetset to use for a specific UI. If no specific widgetset is
+ * required, <code>null</code> is returned.
+ * <p>
+ * The default implementation uses the @{@link Widgetset} annotation if it's
+ * defined for the UI class.
+ *
+ * @param request
+ * the wrapped request for which to get a widgetset
+ * @param uiClass
+ * the UI class to get a widgetset for
+ * @return the name of the widgetset, or <code>null</code> if the default
+ * widgetset should be used
+ *
+ */
+ public String getWidgetsetForUI(WrappedRequest request,
+ Class<? extends UI> uiClass);
+
+ /**
+ * Finds the theme to use for a specific UI. If no specific theme is
+ * required, <code>null</code> is returned.
+ *
+ * TODO Tell what the default implementation does once it does something.
+ *
+ * @param uI
+ * the UI to get a theme for
+ * @return the name of the theme, or <code>null</code> if the default theme
+ * should be used
+ *
+ */
+ 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/UnsupportedBrowserHandler.java b/server/src/com/vaadin/server/UnsupportedBrowserHandler.java
index 325edb5d61..dccbf7ba7b 100644
--- a/server/src/com/vaadin/server/UnsupportedBrowserHandler.java
+++ b/server/src/com/vaadin/server/UnsupportedBrowserHandler.java
@@ -18,7 +18,6 @@ package com.vaadin.server;
import java.io.IOException;
import java.io.Writer;
-import com.vaadin.Application;
/**
* A {@link RequestHandler} that presents an informative page if the browser in
@@ -36,7 +35,7 @@ public class UnsupportedBrowserHandler implements RequestHandler {
public static final String FORCE_LOAD_COOKIE = "vaadinforceload=1";
@Override
- public boolean handleRequest(Application application,
+ public boolean handleRequest(VaadinSession application,
WrappedRequest request, WrappedResponse response)
throws IOException {
diff --git a/server/src/com/vaadin/server/VaadinPortlet.java b/server/src/com/vaadin/server/VaadinPortlet.java
index 4d6d7b84f0..941d96ea25 100644
--- a/server/src/com/vaadin/server/VaadinPortlet.java
+++ b/server/src/com/vaadin/server/VaadinPortlet.java
@@ -16,6 +16,7 @@
package com.vaadin.server;
import java.io.BufferedWriter;
+import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -24,11 +25,13 @@ import java.io.PrintWriter;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
+import java.net.URL;
import java.security.GeneralSecurityException;
import java.util.Enumeration;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
+import java.util.logging.Level;
import java.util.logging.Logger;
import javax.portlet.ActionRequest;
@@ -52,11 +55,12 @@ import javax.servlet.http.HttpServletResponse;
import com.liferay.portal.kernel.util.PortalClassInvoker;
import com.liferay.portal.kernel.util.PropsUtil;
-import com.vaadin.Application;
-import com.vaadin.Application.ApplicationStartEvent;
+import com.vaadin.DefaultApplicationConfiguration;
import com.vaadin.server.AbstractCommunicationManager.Callback;
import com.vaadin.server.ServletPortletHelper.ApplicationClassException;
+import com.vaadin.server.VaadinSession.ApplicationStartEvent;
import com.vaadin.ui.UI;
+import com.vaadin.util.CurrentInstance;
/**
* Portlet 2.0 base class. This replaces the servlet in servlet/portlet 1.0
@@ -75,8 +79,8 @@ public class VaadinPortlet extends GenericPortlet implements Constants {
private final VaadinPortlet portlet;
public PortletDeploymentConfiguration(VaadinPortlet portlet,
- Properties applicationProperties) {
- super(portlet.getClass(), applicationProperties);
+ ApplicationConfiguration applicationConfiguration) {
+ super(applicationConfiguration);
this.portlet = portlet;
}
@@ -87,8 +91,8 @@ public class VaadinPortlet extends GenericPortlet implements Constants {
@Override
public String getConfiguredWidgetset(WrappedRequest request) {
- String widgetset = getApplicationOrSystemProperty(
- PARAMETER_WIDGETSET, null);
+ String widgetset = getApplicationConfiguration()
+ .getApplicationOrSystemProperty(PARAMETER_WIDGETSET, null);
if (widgetset == null) {
// If no widgetset defined for the application, check the
@@ -152,6 +156,29 @@ public class VaadinPortlet extends GenericPortlet implements Constants {
public SystemMessages getSystemMessages() {
return ServletPortletHelper.DEFAULT_SYSTEM_MESSAGES;
}
+
+ @Override
+ public File getBaseDirectory() {
+ PortletContext context = getPortlet().getPortletContext();
+ String resultPath = context.getRealPath("/");
+ if (resultPath != null) {
+ return new File(resultPath);
+ } else {
+ try {
+ final URL url = context.getResource("/");
+ return new File(url.getFile());
+ } catch (final Exception e) {
+ // FIXME: Handle exception
+ getLogger()
+ .log(Level.INFO,
+ "Cannot access base directory, possible security issue "
+ + "with Application Server or Servlet Container",
+ e);
+ }
+ }
+ return null;
+ }
+
}
public static class WrappedHttpAndPortletRequest extends
@@ -293,7 +320,7 @@ public class VaadinPortlet extends GenericPortlet implements Constants {
// TODO Can we close the application when the portlet is removed? Do we know
// when the portlet is removed?
- private DeploymentConfiguration deploymentConfiguration;
+ private PortletDeploymentConfiguration deploymentConfiguration;
private AddonContext addonContext;
@Override
@@ -318,15 +345,23 @@ public class VaadinPortlet extends GenericPortlet implements Constants {
config.getInitParameter(name));
}
- deploymentConfiguration = createDeploymentConfiguration(applicationProperties);
+ ApplicationConfiguration applicationConfiguration = createApplicationConfiguration(applicationProperties);
+ deploymentConfiguration = createDeploymentConfiguration(applicationConfiguration);
addonContext = new AddonContext(deploymentConfiguration);
addonContext.init();
}
- protected DeploymentConfiguration createDeploymentConfiguration(
+ protected ApplicationConfiguration createApplicationConfiguration(
Properties applicationProperties) {
- return new PortletDeploymentConfiguration(this, applicationProperties);
+ return new DefaultApplicationConfiguration(getClass(),
+ applicationProperties);
+ }
+
+ protected PortletDeploymentConfiguration createDeploymentConfiguration(
+ ApplicationConfiguration applicationConfiguration) {
+ return new PortletDeploymentConfiguration(this,
+ applicationConfiguration);
}
@Override
@@ -383,16 +418,6 @@ public class VaadinPortlet extends GenericPortlet implements Constants {
&& request.getResourceID().equals("DUMMY");
}
- /**
- * Returns true if the portlet is running in production mode. Production
- * mode disables all debug facilities.
- *
- * @return true if in production mode, false if in debug mode
- */
- public boolean isProductionMode() {
- return deploymentConfiguration.isProductionMode();
- }
-
protected void handleRequest(PortletRequest request,
PortletResponse response) throws PortletException, IOException {
RequestTimer requestTimer = new RequestTimer();
@@ -406,6 +431,9 @@ public class VaadinPortlet extends GenericPortlet implements Constants {
WrappedPortletResponse wrappedResponse = new WrappedPortletResponse(
response, getDeploymentConfiguration());
+ CurrentInstance.set(WrappedRequest.class, wrappedRequest);
+ CurrentInstance.set(WrappedResponse.class, wrappedResponse);
+
RequestType requestType = getRequestType(wrappedRequest);
if (requestType == RequestType.UNKNOWN) {
@@ -427,9 +455,7 @@ public class VaadinPortlet extends GenericPortlet implements Constants {
serveStaticResources((ResourceRequest) request,
(ResourceResponse) response);
} else {
- Application application = null;
- boolean transactionStarted = false;
- boolean requestStarted = false;
+ VaadinSession application = null;
boolean applicationRunning = false;
try {
@@ -441,19 +467,16 @@ public class VaadinPortlet extends GenericPortlet implements Constants {
if (application == null) {
return;
}
- Application.setCurrent(application);
+ VaadinSession.setCurrent(application);
/*
* Get or create an application context and an application
* manager for the session
*/
- PortletApplicationContext2 applicationContext = getApplicationContext(request
- .getPortletSession());
- applicationContext.setResponse(response);
- applicationContext.setPortletConfig(getPortletConfig());
+ VaadinPortletSession applicationContext = (VaadinPortletSession) application;
- PortletCommunicationManager applicationManager = applicationContext
- .getApplicationManager(application);
+ PortletCommunicationManager applicationManager = (PortletCommunicationManager) applicationContext
+ .getApplicationManager();
if (requestType == RequestType.CONNECTOR_RESOURCE) {
applicationManager.serveConnectorResource(wrappedRequest,
@@ -469,27 +492,8 @@ public class VaadinPortlet extends GenericPortlet implements Constants {
applicationContext.getBrowser().updateRequestDetails(
wrappedRequest);
- /*
- * Call application requestStart before Application.init() is
- * called (bypasses the limitation in TransactionListener)
- */
- if (application instanceof PortletRequestListener) {
- ((PortletRequestListener) application).onRequestStart(
- request, response);
- requestStarted = true;
- }
-
- /* Start the newly created application */
- startApplication(request, application, applicationContext);
applicationRunning = true;
- /*
- * Transaction starts. Call transaction listeners. Transaction
- * end is called in the finally block below.
- */
- applicationContext.startTransaction(application, request);
- transactionStarted = true;
-
/* Notify listeners */
// Finds the window within the application
@@ -525,19 +529,17 @@ public class VaadinPortlet extends GenericPortlet implements Constants {
// TODO Should this happen before or after the transaction
// starts?
if (request instanceof RenderRequest) {
- applicationContext.firePortletRenderRequest(application,
- uI, (RenderRequest) request,
- (RenderResponse) response);
+ applicationContext.firePortletRenderRequest(uI,
+ (RenderRequest) request, (RenderResponse) response);
} else if (request instanceof ActionRequest) {
- applicationContext.firePortletActionRequest(application,
- uI, (ActionRequest) request,
- (ActionResponse) response);
+ applicationContext.firePortletActionRequest(uI,
+ (ActionRequest) request, (ActionResponse) response);
} else if (request instanceof EventRequest) {
- applicationContext.firePortletEventRequest(application, uI,
+ applicationContext.firePortletEventRequest(uI,
(EventRequest) request, (EventResponse) response);
} else if (request instanceof ResourceRequest) {
- applicationContext.firePortletResourceRequest(application,
- uI, (ResourceRequest) request,
+ applicationContext.firePortletResourceRequest(uI,
+ (ResourceRequest) request,
(ResourceResponse) response);
}
@@ -588,29 +590,10 @@ public class VaadinPortlet extends GenericPortlet implements Constants {
application.closeInactiveUIs();
}
- // Notifies transaction end
- try {
- if (transactionStarted) {
- ((PortletApplicationContext2) application.getContext())
- .endTransaction(application, request);
- }
- } finally {
- try {
- if (requestStarted) {
- ((PortletRequestListener) application)
- .onRequestEnd(request, response);
+ CurrentInstance.clearAll();
- }
- } finally {
- UI.setCurrent(null);
- Application.setCurrent(null);
-
- PortletSession session = request
- .getPortletSession(false);
- if (session != null) {
- requestTimer.stop(getApplicationContext(session));
- }
- }
+ if (application != null) {
+ requestTimer.stop(application);
}
}
}
@@ -640,7 +623,7 @@ public class VaadinPortlet extends GenericPortlet implements Constants {
}
- protected DeploymentConfiguration getDeploymentConfiguration() {
+ protected PortletDeploymentConfiguration getDeploymentConfiguration() {
return deploymentConfiguration;
}
@@ -668,8 +651,8 @@ public class VaadinPortlet extends GenericPortlet implements Constants {
*/
private void handleOtherRequest(WrappedPortletRequest request,
WrappedResponse response, RequestType requestType,
- Application application,
- PortletApplicationContext2 applicationContext,
+ VaadinSession application,
+ VaadinPortletSession applicationContext,
PortletCommunicationManager applicationManager)
throws PortletException, IOException, MalformedURLException {
if (requestType == RequestType.APPLICATION_RESOURCE
@@ -776,30 +759,14 @@ public class VaadinPortlet extends GenericPortlet implements Constants {
&& (request.getParameter(URL_PARAMETER_REPAINT_ALL).equals("1"));
}
- private void startApplication(PortletRequest request,
- Application application, PortletApplicationContext2 context)
- throws PortletException, MalformedURLException {
- if (!application.isRunning()) {
- Locale locale = request.getLocale();
- application.setLocale(locale);
- // No application URL when running inside a portlet
- application.start(new ApplicationStartEvent(null,
- getDeploymentConfiguration(), context));
- addonContext.fireApplicationStarted(application);
- }
- }
-
private void endApplication(PortletRequest request,
- PortletResponse response, Application application)
+ PortletResponse response, VaadinSession application)
throws IOException {
- final PortletSession session = request.getPortletSession();
- if (session != null) {
- getApplicationContext(session).removeApplication(application);
- }
+ application.removeFromSession();
// Do not send any redirects when running inside a portlet.
}
- private Application findApplicationInstance(
+ private VaadinSession findApplicationInstance(
WrappedPortletRequest wrappedRequest, RequestType requestType)
throws PortletException, SessionExpiredException,
MalformedURLException {
@@ -809,7 +776,7 @@ public class VaadinPortlet extends GenericPortlet implements Constants {
request, requestType);
/* Find an existing application for this request. */
- Application application = getExistingApplication(request,
+ VaadinSession application = getExistingApplication(request,
requestCanCreateApplication);
if (application != null) {
@@ -825,7 +792,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;
@@ -837,35 +804,61 @@ public class VaadinPortlet extends GenericPortlet implements Constants {
// No existing application was found
if (requestCanCreateApplication) {
- return createApplication(request);
+ return createAndRegisterApplication(request);
} else {
throw new SessionExpiredException();
}
}
- private void closeApplication(Application application,
+ private void closeApplication(VaadinSession application,
PortletSession session) {
if (application == null) {
return;
}
application.close();
- if (session != null) {
- PortletApplicationContext2 context = getApplicationContext(session);
- context.removeApplication(application);
- }
+ application.removeFromSession();
}
- private Application createApplication(PortletRequest request)
- throws PortletException, MalformedURLException {
- Application newApplication = getNewApplication(request);
- final PortletApplicationContext2 context = getApplicationContext(request
- .getPortletSession());
- context.addApplication(newApplication, request.getWindowID());
+ private VaadinSession createAndRegisterApplication(PortletRequest request)
+ throws PortletException {
+ VaadinSession newApplication = createApplication(request);
+
+ try {
+ ServletPortletHelper.checkUiProviders(newApplication);
+ } catch (ApplicationClassException e) {
+ throw new PortletException(e);
+ }
+
+ newApplication.storeInSession(new WrappedPortletSession(request
+ .getPortletSession()));
+
+ Locale locale = request.getLocale();
+ newApplication.setLocale(locale);
+ // No application URL when running inside a portlet
+ newApplication.start(new ApplicationStartEvent(null,
+ getDeploymentConfiguration().getApplicationConfiguration(),
+ new PortletCommunicationManager(newApplication)));
+ addonContext.fireApplicationStarted(newApplication);
+
return newApplication;
}
- private Application getExistingApplication(PortletRequest request,
+ protected VaadinPortletSession createApplication(
+ PortletRequest request) throws PortletException {
+ VaadinPortletSession application = new VaadinPortletSession();
+
+ try {
+ ServletPortletHelper.initDefaultUIProvider(application,
+ getDeploymentConfiguration());
+ } catch (ApplicationClassException e) {
+ throw new PortletException(e);
+ }
+
+ return application;
+ }
+
+ private VaadinSession getExistingApplication(PortletRequest request,
boolean allowSessionCreation) throws MalformedURLException,
SessionExpiredException {
@@ -876,43 +869,21 @@ public class VaadinPortlet extends GenericPortlet implements Constants {
throw new SessionExpiredException();
}
- PortletApplicationContext2 context = getApplicationContext(session);
- Application application = context.getApplicationForWindowId(request
- .getWindowID());
+ VaadinSession application = VaadinSession
+ .getForSession(new WrappedPortletSession(session));
if (application == null) {
return null;
}
- if (application.isRunning()) {
- return application;
+ if (!application.isRunning()) {
+ application.removeFromSession();
+ return null;
}
- // application found but not running
- context.removeApplication(application);
-
- 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);
- }
+ return application;
}
private void handleServiceException(WrappedPortletRequest request,
- WrappedPortletResponse response, Application application,
+ WrappedPortletResponse response, VaadinSession application,
Throwable e) throws IOException, PortletException {
// TODO Check that this error handler is working when running inside a
// portlet
@@ -1013,21 +984,6 @@ public class VaadinPortlet extends GenericPortlet implements Constants {
outWriter.close();
}
- /**
- *
- * Gets the application context for a PortletSession. If no context is
- * currently stored in a session a new context is created and stored in the
- * session.
- *
- * @param portletSession
- * the portlet session.
- * @return the application context for the session.
- */
- protected PortletApplicationContext2 getApplicationContext(
- PortletSession portletSession) {
- return PortletApplicationContext2.getApplicationContext(portletSession);
- }
-
private static final Logger getLogger() {
return Logger.getLogger(VaadinPortlet.class.getName());
}
diff --git a/server/src/com/vaadin/server/PortletApplicationContext2.java b/server/src/com/vaadin/server/VaadinPortletSession.java
index cea97bc939..8d1ae84fca 100644
--- a/server/src/com/vaadin/server/PortletApplicationContext2.java
+++ b/server/src/com/vaadin/server/VaadinPortletSession.java
@@ -15,15 +15,12 @@
*/
package com.vaadin.server;
-import java.io.File;
import java.io.Serializable;
-import java.net.URL;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
-import java.util.logging.Level;
-import java.util.logging.Logger;
import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
@@ -44,8 +41,8 @@ import javax.portlet.StateAwareResponse;
import javax.servlet.http.HttpSessionBindingListener;
import javax.xml.namespace.QName;
-import com.vaadin.Application;
import com.vaadin.ui.UI;
+import com.vaadin.util.CurrentInstance;
/**
* TODO Write documentation, fix JavaDoc tags.
@@ -56,16 +53,9 @@ import com.vaadin.ui.UI;
* @author peholmst
*/
@SuppressWarnings("serial")
-public class PortletApplicationContext2 extends ApplicationContext {
+public class VaadinPortletSession extends VaadinSession {
- protected Map<Application, Set<PortletListener>> portletListeners = new HashMap<Application, Set<PortletListener>>();
-
- protected transient PortletSession session;
- protected transient PortletConfig portletConfig;
-
- protected HashMap<String, Application> portletWindowIdToApplicationMap = new HashMap<String, Application>();
-
- private transient PortletResponse response;
+ private final Set<PortletListener> portletListeners = new LinkedHashSet<PortletListener>();
private final Map<String, QName> eventActionDestinationMap = new HashMap<String, QName>();
private final Map<String, Serializable> eventActionValueMap = new HashMap<String, Serializable>();
@@ -73,125 +63,50 @@ public class PortletApplicationContext2 extends ApplicationContext {
private final Map<String, String> sharedParameterActionNameMap = new HashMap<String, String>();
private final Map<String, String> sharedParameterActionValueMap = new HashMap<String, String>();
- @Override
- public File getBaseDirectory() {
- String resultPath = session.getPortletContext().getRealPath("/");
- if (resultPath != null) {
- return new File(resultPath);
- } else {
- try {
- final URL url = session.getPortletContext().getResource("/");
- return new File(url.getFile());
- } catch (final Exception e) {
- // FIXME: Handle exception
- getLogger()
- .log(Level.INFO,
- "Cannot access base directory, possible security issue "
- + "with Application Server or Servlet Container",
- e);
- }
- }
- return null;
- }
-
- 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;
+ public PortletSession getPortletSession() {
+ WrappedSession wrappedSession = getSession();
+ PortletSession session = ((WrappedPortletSession) wrappedSession)
+ .getPortletSession();
+ return session;
}
- protected PortletCommunicationManager createPortletCommunicationManager(
- Application application) {
- return new PortletCommunicationManager(application);
- }
+ private PortletResponse getCurrentResponse() {
+ WrappedPortletResponse currentResponse = (WrappedPortletResponse) CurrentInstance
+ .get(WrappedResponse.class);
- public static PortletApplicationContext2 getApplicationContext(
- PortletSession session) {
- Object cxattr = session.getAttribute(PortletApplicationContext2.class
- .getName());
- PortletApplicationContext2 cx = null;
- // can be false also e.g. if old context comes from another
- // classloader when using
- // <private-session-attributes>false</private-session-attributes>
- // and redeploying the portlet - see #7461
- if (cxattr instanceof PortletApplicationContext2) {
- cx = (PortletApplicationContext2) cxattr;
- }
- if (cx == null) {
- cx = new PortletApplicationContext2();
- session.setAttribute(PortletApplicationContext2.class.getName(), cx);
- }
- if (cx.session == null) {
- cx.session = session;
+ if (currentResponse != null) {
+ return currentResponse.getPortletResponse();
+ } else {
+ return null;
}
- 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() {
- return session;
}
public PortletConfig getPortletConfig() {
- return portletConfig;
+ WrappedPortletResponse response = (WrappedPortletResponse) CurrentInstance
+ .get(WrappedResponse.class);
+ return response.getDeploymentConfiguration().getPortlet()
+ .getPortletConfig();
}
- public void setPortletConfig(PortletConfig config) {
- portletConfig = config;
+ public void addPortletListener(PortletListener listener) {
+ portletListeners.add(listener);
}
- public void addPortletListener(Application app, PortletListener listener) {
- Set<PortletListener> l = portletListeners.get(app);
- if (l == null) {
- l = new LinkedHashSet<PortletListener>();
- portletListeners.put(app, l);
- }
- l.add(listener);
+ public void removePortletListener(PortletListener listener) {
+ portletListeners.remove(listener);
}
- public void removePortletListener(Application app, PortletListener listener) {
- Set<PortletListener> l = portletListeners.get(app);
- if (l != null) {
- l.remove(listener);
+ public void firePortletRenderRequest(UI uI, RenderRequest request,
+ RenderResponse response) {
+ for (PortletListener l : new ArrayList<PortletListener>(
+ portletListeners)) {
+ l.handleRenderRequest(request, new RestrictedRenderResponse(
+ response), uI);
}
}
- public void firePortletRenderRequest(Application app, UI uI,
- RenderRequest request, RenderResponse response) {
- Set<PortletListener> listeners = portletListeners.get(app);
- if (listeners != null) {
- for (PortletListener l : listeners) {
- l.handleRenderRequest(request, new RestrictedRenderResponse(
- response), uI);
- }
- }
- }
-
- public void firePortletActionRequest(Application app, UI uI,
- ActionRequest request, ActionResponse response) {
+ public void firePortletActionRequest(UI uI, ActionRequest request,
+ ActionResponse response) {
String key = request.getParameter(ActionRequest.ACTION_NAME);
if (eventActionDestinationMap.containsKey(key)) {
// this action request is only to send queued portlet events
@@ -209,32 +124,26 @@ public class PortletApplicationContext2 extends ApplicationContext {
sharedParameterActionValueMap.remove(key);
} else {
// normal action request, notify listeners
- Set<PortletListener> listeners = portletListeners.get(app);
- if (listeners != null) {
- for (PortletListener l : listeners) {
- l.handleActionRequest(request, response, uI);
- }
+ for (PortletListener l : new ArrayList<PortletListener>(
+ portletListeners)) {
+ l.handleActionRequest(request, response, uI);
}
}
}
- public void firePortletEventRequest(Application app, UI uI,
- EventRequest request, EventResponse response) {
- Set<PortletListener> listeners = portletListeners.get(app);
- if (listeners != null) {
- for (PortletListener l : listeners) {
- l.handleEventRequest(request, response, uI);
- }
+ public void firePortletEventRequest(UI uI, EventRequest request,
+ EventResponse response) {
+ for (PortletListener l : new ArrayList<PortletListener>(
+ portletListeners)) {
+ l.handleEventRequest(request, response, uI);
}
}
- public void firePortletResourceRequest(Application app, UI uI,
- ResourceRequest request, ResourceResponse response) {
- Set<PortletListener> listeners = portletListeners.get(app);
- if (listeners != null) {
- for (PortletListener l : listeners) {
- l.handleResourceRequest(request, response, uI);
- }
+ public void firePortletResourceRequest(UI uI, ResourceRequest request,
+ ResourceResponse response) {
+ for (PortletListener l : new ArrayList<PortletListener>(
+ portletListeners)) {
+ l.handleResourceRequest(request, response, uI);
}
}
@@ -254,17 +163,6 @@ public class PortletApplicationContext2 extends ApplicationContext {
}
/**
- * This is for use by {@link VaadinPortlet} only.
- *
- * TODO cleaner implementation, now "semi-static"!
- *
- * @param mimeResponse
- */
- void setResponse(PortletResponse response) {
- this.response = response;
- }
-
- /**
* Creates a new action URL.
*
* @param action
@@ -273,6 +171,7 @@ public class PortletApplicationContext2 extends ApplicationContext {
*/
public PortletURL generateActionURL(String action) {
PortletURL url = null;
+ PortletResponse response = getCurrentResponse();
if (response instanceof MimeResponse) {
url = ((MimeResponse) response).createActionURL();
url.setParameter("javax.portlet.action", action);
@@ -305,6 +204,7 @@ public class PortletApplicationContext2 extends ApplicationContext {
*/
public void sendPortletEvent(UI uI, QName name, Serializable value)
throws IllegalStateException {
+ PortletResponse response = getCurrentResponse();
if (response instanceof MimeResponse) {
String actionKey = "" + System.currentTimeMillis();
while (eventActionDestinationMap.containsKey(actionKey)) {
@@ -351,6 +251,7 @@ public class PortletApplicationContext2 extends ApplicationContext {
*/
public void setSharedRenderParameter(UI uI, String name, String value)
throws IllegalStateException {
+ PortletResponse response = getCurrentResponse();
if (response instanceof MimeResponse) {
String actionKey = "" + System.currentTimeMillis();
while (sharedParameterActionNameMap.containsKey(actionKey)) {
@@ -390,6 +291,7 @@ public class PortletApplicationContext2 extends ApplicationContext {
*/
public void setPortletMode(UI uI, PortletMode portletMode)
throws IllegalStateException, PortletModeException {
+ PortletResponse response = getCurrentResponse();
if (response instanceof MimeResponse) {
PortletURL url = ((MimeResponse) response).createRenderURL();
url.setPortletMode(portletMode);
@@ -402,13 +304,4 @@ public class PortletApplicationContext2 extends ApplicationContext {
"Portlet mode can only be changed from a portlet request");
}
}
-
- @Override
- public int getMaxInactiveInterval() {
- return getPortletSession().getMaxInactiveInterval();
- }
-
- private Logger getLogger() {
- return Logger.getLogger(PortletApplicationContext2.class.getName());
- }
}
diff --git a/server/src/com/vaadin/server/VaadinServlet.java b/server/src/com/vaadin/server/VaadinServlet.java
index a10ad965c5..d2e04da2e9 100644
--- a/server/src/com/vaadin/server/VaadinServlet.java
+++ b/server/src/com/vaadin/server/VaadinServlet.java
@@ -16,6 +16,7 @@
package com.vaadin.server;
import java.io.BufferedWriter;
+import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -30,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;
@@ -44,12 +44,13 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
-import com.vaadin.Application;
-import com.vaadin.Application.ApplicationStartEvent;
+import com.vaadin.DefaultApplicationConfiguration;
import com.vaadin.server.AbstractCommunicationManager.Callback;
import com.vaadin.server.ServletPortletHelper.ApplicationClassException;
+import com.vaadin.server.VaadinSession.ApplicationStartEvent;
import com.vaadin.shared.ApplicationConstants;
import com.vaadin.ui.UI;
+import com.vaadin.util.CurrentInstance;
@SuppressWarnings("serial")
public class VaadinServlet extends HttpServlet implements Constants {
@@ -59,8 +60,8 @@ public class VaadinServlet extends HttpServlet implements Constants {
private final VaadinServlet servlet;
public ServletDeploymentConfiguration(VaadinServlet servlet,
- Properties applicationProperties) {
- super(servlet.getClass(), applicationProperties);
+ ApplicationConfiguration applicationProperties) {
+ super(applicationProperties);
this.servlet = servlet;
}
@@ -74,8 +75,9 @@ public class VaadinServlet extends HttpServlet implements Constants {
.cast(request);
String staticFileLocation;
// if property is defined in configurations, use that
- staticFileLocation = getApplicationOrSystemProperty(
- PARAMETER_VAADIN_RESOURCES, null);
+ staticFileLocation = getApplicationConfiguration()
+ .getApplicationOrSystemProperty(PARAMETER_VAADIN_RESOURCES,
+ null);
if (staticFileLocation != null) {
return staticFileLocation;
}
@@ -111,9 +113,10 @@ public class VaadinServlet extends HttpServlet implements Constants {
@Override
public String getConfiguredWidgetset(WrappedRequest request) {
- return getApplicationOrSystemProperty(
- VaadinServlet.PARAMETER_WIDGETSET,
- VaadinServlet.DEFAULT_WIDGETSET);
+ return getApplicationConfiguration()
+ .getApplicationOrSystemProperty(
+ VaadinServlet.PARAMETER_WIDGETSET,
+ VaadinServlet.DEFAULT_WIDGETSET);
}
@Override
@@ -136,6 +139,16 @@ public class VaadinServlet extends HttpServlet implements Constants {
public SystemMessages getSystemMessages() {
return ServletPortletHelper.DEFAULT_SYSTEM_MESSAGES;
}
+
+ @Override
+ public File getBaseDirectory() {
+ final String realPath = VaadinServlet.getResourcePath(
+ servlet.getServletContext(), "/");
+ if (realPath == null) {
+ return null;
+ }
+ return new File(realPath);
+ }
}
private static class AbstractApplicationServletWrapper implements Callback {
@@ -200,15 +213,23 @@ public class VaadinServlet extends HttpServlet implements Constants {
servletConfig.getInitParameter(name));
}
- deploymentConfiguration = createDeploymentConfiguration(applicationProperties);
+ ApplicationConfiguration applicationConfiguration = createApplicationConfiguration(applicationProperties);
+ deploymentConfiguration = createDeploymentConfiguration(applicationConfiguration);
addonContext = new AddonContext(deploymentConfiguration);
addonContext.init();
}
- protected ServletDeploymentConfiguration createDeploymentConfiguration(
+ protected ApplicationConfiguration createApplicationConfiguration(
Properties applicationProperties) {
- return new ServletDeploymentConfiguration(this, applicationProperties);
+ return new DefaultApplicationConfiguration(getClass(),
+ applicationProperties);
+ }
+
+ protected ServletDeploymentConfiguration createDeploymentConfiguration(
+ ApplicationConfiguration applicationConfiguration) {
+ return new ServletDeploymentConfiguration(this,
+ applicationConfiguration);
}
@Override
@@ -219,26 +240,6 @@ public class VaadinServlet extends HttpServlet implements Constants {
}
/**
- * Returns true if the servlet is running in production mode. Production
- * mode disables all debug facilities.
- *
- * @return true if in production mode, false if in debug mode
- */
- public boolean isProductionMode() {
- return getDeploymentConfiguration().isProductionMode();
- }
-
- /**
- * Returns the number of seconds the browser should cache a file. Default is
- * 1 hour (3600 s).
- *
- * @return The number of seconds files are cached in the browser
- */
- public int getResourceCacheTime() {
- return getDeploymentConfiguration().getResourceCacheTime();
- }
-
- /**
* Receives standard HTTP requests from the public service method and
* dispatches them.
*
@@ -267,6 +268,9 @@ public class VaadinServlet extends HttpServlet implements Constants {
RequestTimer requestTimer = new RequestTimer();
requestTimer.start();
+ CurrentInstance.set(WrappedResponse.class, response);
+ CurrentInstance.set(WrappedRequest.class, request);
+
AbstractApplicationServletWrapper servletWrapper = new AbstractApplicationServletWrapper(
this);
@@ -280,9 +284,7 @@ public class VaadinServlet extends HttpServlet implements Constants {
return;
}
- Application application = null;
- boolean transactionStarted = false;
- boolean requestStarted = false;
+ VaadinSession application = null;
boolean applicationRunning = false;
try {
@@ -309,16 +311,15 @@ public class VaadinServlet extends HttpServlet implements Constants {
if (application == null) {
return;
}
- Application.setCurrent(application);
+ VaadinSession.setCurrent(application);
/*
* Get or create a WebApplicationContext and an ApplicationManager
* for the session
*/
- ServletApplicationContext webApplicationContext = getApplicationContext(request
- .getSession());
- CommunicationManager applicationManager = webApplicationContext
- .getApplicationManager(application, this);
+ VaadinServletSession webApplicationContext = (VaadinServletSession) application;
+ CommunicationManager applicationManager = (CommunicationManager) webApplicationContext
+ .getApplicationManager();
if (requestType == RequestType.CONNECTOR_RESOURCE) {
applicationManager.serveConnectorResource(request, response);
@@ -332,27 +333,8 @@ public class VaadinServlet extends HttpServlet implements Constants {
/* Update browser information from the request */
webApplicationContext.getBrowser().updateRequestDetails(request);
- /*
- * Call application requestStart before Application.init() is called
- * (bypasses the limitation in TransactionListener)
- */
- if (application instanceof HttpServletRequestListener) {
- ((HttpServletRequestListener) application).onRequestStart(
- request, response);
- requestStarted = true;
- }
-
- // Start the application if it's newly created
- startApplication(request, application, webApplicationContext);
applicationRunning = true;
- /*
- * Transaction starts. Call transaction listeners. Transaction end
- * is called in the finally block below.
- */
- webApplicationContext.startTransaction(application, request);
- transactionStarted = true;
-
/* Handle the request */
if (requestType == RequestType.FILE_UPLOAD) {
// UI is resolved in communication manager
@@ -400,31 +382,11 @@ public class VaadinServlet extends HttpServlet implements Constants {
application.closeInactiveUIs();
}
- // Notifies transaction end
- try {
- if (transactionStarted) {
- ((ServletApplicationContext) application.getContext())
- .endTransaction(application, request);
-
- }
-
- } finally {
- try {
- if (requestStarted) {
- ((HttpServletRequestListener) application)
- .onRequestEnd(request, response);
- }
- } finally {
- UI.setCurrent(null);
- Application.setCurrent(null);
+ CurrentInstance.clearAll();
- HttpSession session = request.getSession(false);
- if (session != null) {
- requestTimer.stop(getApplicationContext(session));
- }
- }
+ if (application != null) {
+ requestTimer.stop(application);
}
-
}
}
@@ -612,7 +574,7 @@ public class VaadinServlet extends HttpServlet implements Constants {
* @throws ServletException
* @throws SessionExpiredException
*/
- private Application findApplicationInstance(HttpServletRequest request,
+ private VaadinSession findApplicationInstance(HttpServletRequest request,
RequestType requestType) throws MalformedURLException,
ServletException, SessionExpiredException {
@@ -620,7 +582,7 @@ public class VaadinServlet extends HttpServlet implements Constants {
request, requestType);
/* Find an existing application for this request. */
- Application application = getExistingApplication(request,
+ VaadinSession application = getExistingApplication(request,
requestCanCreateApplication);
if (application != null) {
@@ -636,7 +598,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;
@@ -652,7 +614,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
@@ -663,6 +625,33 @@ public class VaadinServlet extends HttpServlet implements Constants {
}
+ private VaadinSession createAndRegisterApplication(HttpServletRequest request)
+ throws ServletException, MalformedURLException {
+ VaadinSession newApplication = createApplication(request);
+
+ try {
+ ServletPortletHelper.checkUiProviders(newApplication);
+ } catch (ApplicationClassException e) {
+ throw new ServletException(e);
+ }
+
+ newApplication.storeInSession(new WrappedHttpSession(request
+ .getSession()));
+
+ final URL applicationUrl = getApplicationUrl(request);
+
+ // Initial locale comes from the request
+ Locale locale = request.getLocale();
+ newApplication.setLocale(locale);
+ newApplication.start(new ApplicationStartEvent(applicationUrl,
+ getDeploymentConfiguration().getApplicationConfiguration(),
+ createCommunicationManager(newApplication)));
+
+ addonContext.fireApplicationStarted(newApplication);
+
+ return newApplication;
+ }
+
/**
* Check if the request should create an application if an existing
* application is not found.
@@ -732,19 +721,22 @@ public class VaadinServlet extends HttpServlet implements Constants {
* @throws ServletException
* @throws MalformedURLException
*/
- private Application createApplication(HttpServletRequest request)
- throws ServletException, MalformedURLException {
- Application newApplication = getNewApplication(request);
+ protected VaadinServletSession createApplication(
+ HttpServletRequest request) throws ServletException {
+ VaadinServletSession newApplication = new VaadinServletSession();
- final ServletApplicationContext context = getApplicationContext(request
- .getSession());
- context.addApplication(newApplication);
+ try {
+ ServletPortletHelper.initDefaultUIProvider(newApplication,
+ getDeploymentConfiguration());
+ } catch (ApplicationClassException e) {
+ throw new ServletException(e);
+ }
return newApplication;
}
private void handleServiceException(WrappedHttpServletRequest request,
- WrappedHttpServletResponse response, Application application,
+ WrappedHttpServletResponse response, VaadinSession application,
Throwable e) throws IOException, ServletException {
// if this was an UIDL request, response UIDL back to client
if (getRequestType(request) == RequestType.UIDL) {
@@ -881,62 +873,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
- * @param application
- * @param webApplicationContext
- * @throws ServletException
- * @throws MalformedURLException
- */
- private void startApplication(HttpServletRequest request,
- Application application,
- ServletApplicationContext webApplicationContext)
- throws ServletException, MalformedURLException {
-
- if (!application.isRunning()) {
- // Create application
- final URL applicationUrl = getApplicationUrl(request);
-
- // Initial locale comes from the request
- Locale locale = request.getLocale();
- application.setLocale(locale);
- application.start(new ApplicationStartEvent(applicationUrl,
- getDeploymentConfiguration(), webApplicationContext));
- addonContext.fireApplicationStarted(application);
- }
- }
-
- /**
* Check if this is a request for a static resource and, if it is, serve the
* resource to the client.
*
@@ -1076,8 +1012,10 @@ public class VaadinServlet extends HttpServlet implements Constants {
* cache timeout can be configured by setting the resourceCacheTime
* parameter in web.xml
*/
+ int resourceCacheTime = getDeploymentConfiguration()
+ .getApplicationConfiguration().getResourceCacheTime();
response.setHeader("Cache-Control",
- "max-age= " + String.valueOf(getResourceCacheTime()));
+ "max-age= " + String.valueOf(resourceCacheTime));
}
// Write the resource to the client.
@@ -1331,7 +1269,7 @@ public class VaadinServlet extends HttpServlet implements Constants {
* @throws InstantiationException
* @throws SessionExpiredException
*/
- protected Application getExistingApplication(HttpServletRequest request,
+ protected VaadinSession getExistingApplication(HttpServletRequest request,
boolean allowSessionCreation) throws MalformedURLException,
SessionExpiredException {
@@ -1341,35 +1279,18 @@ public class VaadinServlet extends HttpServlet implements Constants {
throw new SessionExpiredException();
}
- ServletApplicationContext context = getApplicationContext(session);
-
- // Gets application list for the session.
- final Collection<Application> applications = context.getApplications();
+ VaadinSession sessionApplication = getApplicationContext(session);
- // 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 (sessionApplication == null) {
+ return null;
+ }
- 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;
- }
+ if (!sessionApplication.isRunning()) {
+ sessionApplication.removeFromSession();
+ return null;
}
- // Existing application not found
- return null;
+ return sessionApplication;
}
/**
@@ -1385,7 +1306,7 @@ public class VaadinServlet extends HttpServlet implements Constants {
* if the writing failed due to input/output error.
*/
private void endApplication(HttpServletRequest request,
- HttpServletResponse response, Application application)
+ HttpServletResponse response, VaadinSession application)
throws IOException {
String logoutUrl = application.getLogoutURL();
@@ -1395,7 +1316,7 @@ public class VaadinServlet extends HttpServlet implements Constants {
final HttpSession session = request.getSession();
if (session != null) {
- getApplicationContext(session).removeApplication(application);
+ application.removeFromSession();
}
response.sendRedirect(response.encodeRedirectURL(logoutUrl));
@@ -1440,36 +1361,21 @@ public class VaadinServlet extends HttpServlet implements Constants {
&& (request.getParameter(URL_PARAMETER_REPAINT_ALL).equals("1"));
}
- private void closeApplication(Application application, HttpSession session) {
+ private void closeApplication(VaadinSession application, HttpSession session) {
if (application == null) {
return;
}
application.close();
if (session != null) {
- ServletApplicationContext context = getApplicationContext(session);
- context.removeApplication(application);
+ application.removeFromSession();
}
}
- /**
- *
- * Gets the application context from an HttpSession. If no context is
- * currently stored in a session a new context is created and stored in the
- * session.
- *
- * @param session
- * the HTTP session.
- * @return the application context for HttpSession.
- */
- protected ServletApplicationContext getApplicationContext(
- HttpSession session) {
- /*
- * TODO the ApplicationContext.getApplicationContext() should be removed
- * and logic moved here. Now overriding context type is possible, but
- * the whole creation logic should be here. MT 1101
- */
- return ServletApplicationContext.getApplicationContext(session);
+ protected VaadinSession getApplicationContext(final HttpSession session) {
+ VaadinSession sessionApplication = VaadinSession
+ .getForSession(new WrappedHttpSession(session));
+ return sessionApplication;
}
public class RequestError implements Terminal.ErrorEvent, Serializable {
@@ -1492,11 +1398,11 @@ public class VaadinServlet extends HttpServlet implements Constants {
* mananger implementation.
*
* @deprecated Instead of overriding this method, override
- * {@link ServletApplicationContext} implementation via
+ * {@link VaadinServletSession} implementation via
* {@link VaadinServlet#getApplicationContext(HttpSession)}
* method and in that customized implementation return your
* CommunicationManager in
- * {@link ServletApplicationContext#getApplicationManager(Application, VaadinServlet)}
+ * {@link VaadinServletSession#getApplicationManager(VaadinSession, VaadinServlet)}
* method.
*
* @param application
@@ -1504,7 +1410,7 @@ public class VaadinServlet extends HttpServlet implements Constants {
*/
@Deprecated
public CommunicationManager createCommunicationManager(
- Application application) {
+ VaadinSession application) {
return new CommunicationManager(application);
}
diff --git a/server/src/com/vaadin/server/VaadinServletSession.java b/server/src/com/vaadin/server/VaadinServletSession.java
new file mode 100644
index 0000000000..72b744da72
--- /dev/null
+++ b/server/src/com/vaadin/server/VaadinServletSession.java
@@ -0,0 +1,100 @@
+/*
+ * 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.Enumeration;
+import java.util.HashMap;
+
+import javax.servlet.http.HttpSession;
+import javax.servlet.http.HttpSessionBindingEvent;
+import javax.servlet.http.HttpSessionBindingListener;
+
+import com.vaadin.util.CurrentInstance;
+
+/**
+ * Web application context for Vaadin applications.
+ *
+ * This is automatically added as a {@link HttpSessionBindingListener} when
+ * added to a {@link HttpSession}.
+ *
+ * @author Vaadin Ltd.
+ * @since 3.1
+ */
+@SuppressWarnings("serial")
+public class VaadinServletSession extends VaadinSession {
+
+ private transient boolean reinitializingSession = false;
+
+ @Override
+ public void valueUnbound(HttpSessionBindingEvent event) {
+ if (!reinitializingSession) {
+ // Avoid closing the application if we are only reinitializing the
+ // session. Closing the application would cause the state to be lost
+ // and a new application to be created, which is not what we want.
+ super.valueUnbound(event);
+ }
+ }
+
+ /**
+ * Discards the current session and creates a new session with the same
+ * contents. The purpose of this is to introduce a new session key in order
+ * to avoid session fixation attacks.
+ */
+ public void reinitializeSession() {
+
+ HttpSession oldSession = getHttpSession();
+
+ // Stores all attributes (security key, reference to this context
+ // instance) so they can be added to the new session
+ HashMap<String, Object> attrs = new HashMap<String, Object>();
+ for (Enumeration<String> e = oldSession.getAttributeNames(); e
+ .hasMoreElements();) {
+ String name = e.nextElement();
+ attrs.put(name, oldSession.getAttribute(name));
+ }
+
+ // Invalidate the current session, set flag to avoid call to
+ // valueUnbound
+ reinitializingSession = true;
+ oldSession.invalidate();
+ reinitializingSession = false;
+
+ // Create a new session
+ HttpSession newSession = WrappedHttpServletRequest.cast(
+ CurrentInstance.get(WrappedRequest.class)).getSession();
+
+ // Restores all attributes (security key, reference to this context
+ // instance)
+ for (String name : attrs.keySet()) {
+ newSession.setAttribute(name, attrs.get(name));
+ }
+
+ // Update the "current session" variable
+ storeInSession(new WrappedHttpSession(newSession));
+ }
+
+ /**
+ * Gets the http-session application is running in.
+ *
+ * @return HttpSession this application context resides in.
+ */
+ public HttpSession getHttpSession() {
+ WrappedSession session = getSession();
+ return ((WrappedHttpSession) session).getHttpSession();
+ }
+
+}
diff --git a/server/src/com/vaadin/server/VaadinSession.java b/server/src/com/vaadin/server/VaadinSession.java
new file mode 100644
index 0000000000..440fc02ee6
--- /dev/null
+++ b/server/src/com/vaadin/server/VaadinSession.java
@@ -0,0 +1,1978 @@
+/*
+ * 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.io.IOException;
+import java.io.Serializable;
+import java.lang.reflect.Method;
+import java.net.SocketException;
+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;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.servlet.http.HttpSessionBindingEvent;
+import javax.servlet.http.HttpSessionBindingListener;
+
+import com.vaadin.data.util.converter.Converter;
+import com.vaadin.data.util.converter.ConverterFactory;
+import com.vaadin.data.util.converter.DefaultConverterFactory;
+import com.vaadin.event.EventRouter;
+import com.vaadin.server.WrappedRequest.BrowserDetails;
+import com.vaadin.shared.ui.ui.UIConstants;
+import com.vaadin.ui.AbstractComponent;
+import com.vaadin.ui.AbstractField;
+import com.vaadin.ui.Table;
+import com.vaadin.ui.UI;
+import com.vaadin.ui.Window;
+import com.vaadin.util.CurrentInstance;
+import com.vaadin.util.ReflectTools;
+
+/**
+ * <p>
+ * Base class required for all Vaadin applications. This class provides all the
+ * basic services required by Vaadin. These services allow external discovery
+ * and manipulation of the user, {@link com.vaadin.ui.Window windows} and
+ * themes, and starting and stopping the application.
+ * </p>
+ *
+ * <p>
+ * As mentioned, all Vaadin applications must inherit this class. However, this
+ * is almost all of what one needs to do to create a fully functional
+ * application. The only thing a class inheriting the <code>Application</code>
+ * needs to do is implement the <code>init</code> method where it creates the
+ * windows it needs to perform its function. Note that all applications must
+ * have at least one window: the main window. The first unnamed window
+ * constructed by an application automatically becomes the main window which
+ * behaves just like other windows with one exception: when accessing windows
+ * using URLs the main window corresponds to the application URL whereas other
+ * windows correspond to a URL gotten by catenating the window's name to the
+ * application URL.
+ * </p>
+ *
+ * <p>
+ * See the class <code>com.vaadin.demo.HelloWorld</code> for a simple example of
+ * a fully working application.
+ * </p>
+ *
+ * <p>
+ * <strong>Window access.</strong> <code>Application</code> provides methods to
+ * list, add and remove the windows it contains.
+ * </p>
+ *
+ * <p>
+ * <strong>Execution control.</strong> This class includes method to start and
+ * finish the execution of the application. Being finished means basically that
+ * no windows will be available from the application anymore.
+ * </p>
+ *
+ * <p>
+ * <strong>Theme selection.</strong> The theme selection process allows a theme
+ * to be specified at three different levels. When a window's theme needs to be
+ * found out, the window itself is queried for a preferred theme. If the window
+ * does not prefer a specific theme, the application containing the window is
+ * queried. If neither the application prefers a theme, the default theme for
+ * the {@link com.vaadin.server.Terminal terminal} is used. The terminal always
+ * defines a default theme.
+ * </p>
+ *
+ * @author Vaadin Ltd.
+ * @since 3.0
+ */
+@SuppressWarnings("serial")
+public class VaadinSession implements Terminal.ErrorListener,
+ HttpSessionBindingListener, Serializable {
+
+ /**
+ * 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.
+ */
+ public static final String UI_PARAMETER = "UI";
+
+ private static final Method BOOTSTRAP_FRAGMENT_METHOD = ReflectTools
+ .findMethod(BootstrapListener.class, "modifyBootstrapFragment",
+ BootstrapFragmentResponse.class);
+ private static final Method BOOTSTRAP_PAGE_METHOD = ReflectTools
+ .findMethod(BootstrapListener.class, "modifyBootstrapPage",
+ BootstrapPageResponse.class);
+
+ /**
+ * An event sent to {@link #start(ApplicationStartEvent)} when a new
+ * Application is being started.
+ *
+ * @since 7.0
+ */
+ public static class ApplicationStartEvent implements Serializable {
+ private final URL applicationUrl;
+
+ private final ApplicationConfiguration configuration;
+
+ private final AbstractCommunicationManager communicationManager;
+
+ /**
+ * @param applicationUrl
+ * the URL the application should respond to.
+ * @param configuration
+ * the application configuration for the application.
+ * @param communicationManager
+ * the communication manager for the application.
+ */
+ public ApplicationStartEvent(URL applicationUrl,
+ ApplicationConfiguration configuration,
+ AbstractCommunicationManager communicationManager) {
+ this.applicationUrl = applicationUrl;
+ this.configuration = configuration;
+ this.communicationManager = communicationManager;
+ }
+
+ /**
+ * Gets the URL the application should respond to.
+ *
+ * @return the URL the application should respond to or
+ * <code>null</code> if the URL is not defined.
+ *
+ * @see VaadinSession#getURL()
+ */
+ public URL getApplicationUrl() {
+ return applicationUrl;
+ }
+
+ /**
+ * Returns the application configuration used by this application.
+ *
+ * @return the deployment configuration.
+ */
+ public ApplicationConfiguration getConfiguration() {
+ return configuration;
+ }
+
+ /**
+ * Gets the communication manager for this application.
+ *
+ * @return the communication manager for this application.
+ *
+ * @see VaadinSession#getCommunicationManager
+ */
+ public AbstractCommunicationManager getCommunicationManager() {
+ return communicationManager;
+ }
+ }
+
+ private final static Logger logger = Logger.getLogger(VaadinSession.class
+ .getName());
+
+ /**
+ * Configuration for the application.
+ */
+ private ApplicationConfiguration configuration;
+
+ /**
+ * The application's URL.
+ */
+ private URL applicationUrl;
+
+ /**
+ * Application status.
+ */
+ private volatile boolean applicationIsRunning = false;
+
+ /**
+ * Default locale of the application.
+ */
+ 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;
+
+ /**
+ * Application wide error handler which is used by default if an error is
+ * left unhandled.
+ */
+ private Terminal.ErrorListener errorHandler = this;
+
+ /**
+ * The converter factory that is used to provide default converters for the
+ * application.
+ */
+ private ConverterFactory converterFactory = new DefaultConverterFactory();
+
+ private LinkedList<RequestHandler> requestHandlers = new LinkedList<RequestHandler>();
+
+ private int nextUIId = 0;
+ private Map<Integer, UI> uIs = new HashMap<Integer, UI>();
+
+ private final Map<String, Integer> retainOnRefreshUIs = new HashMap<String, Integer>();
+
+ private final EventRouter eventRouter = new EventRouter();
+
+ private List<UIProvider> uiProviders = new LinkedList<UIProvider>();
+
+ private GlobalResourceHandler globalResourceHandler;
+
+ protected WebBrowser browser = new WebBrowser();
+
+ private AbstractCommunicationManager communicationManager;
+
+ private long totalSessionTime = 0;
+
+ private long lastRequestTime = -1;
+
+ private transient WrappedSession session;
+
+ /**
+ * @see javax.servlet.http.HttpSessionBindingListener#valueBound(HttpSessionBindingEvent)
+ */
+ @Override
+ public void valueBound(HttpSessionBindingEvent arg0) {
+ // We are not interested in bindings
+ }
+
+ /**
+ * @see javax.servlet.http.HttpSessionBindingListener#valueUnbound(HttpSessionBindingEvent)
+ */
+ @Override
+ public void valueUnbound(HttpSessionBindingEvent event) {
+ // If we are going to be unbound from the session, the session must be
+ // closing
+ close();
+ }
+
+ /**
+ * Get the web browser associated with this application context.
+ *
+ * Because application context is related to the http session and server
+ * maintains one session per browser-instance, each context has exactly one
+ * web browser associated with it.
+ *
+ * @return
+ */
+ public WebBrowser getBrowser() {
+ return browser;
+ }
+
+ /**
+ * @return The total time spent servicing requests in this session.
+ */
+ public long getTotalSessionTime() {
+ return totalSessionTime;
+ }
+
+ /**
+ * Sets the time spent servicing the last request in the session and updates
+ * the total time spent servicing requests in this session.
+ *
+ * @param time
+ * the time spent in the last request.
+ */
+ public void setLastRequestTime(long time) {
+ lastRequestTime = time;
+ totalSessionTime += time;
+ }
+
+ /**
+ * @return the time spent servicing the last request in this session.
+ */
+ public long getLastRequestTime() {
+ return lastRequestTime;
+ }
+
+ /**
+ * Gets the session to which this application context is currently
+ * associated.
+ *
+ * @return the wrapped session for this context
+ */
+ public WrappedSession getSession() {
+ return session;
+ }
+
+ public AbstractCommunicationManager getApplicationManager() {
+ return communicationManager;
+ }
+
+ /**
+ * Gets the URL of the application.
+ *
+ * <p>
+ * This is the URL what can be entered to a browser window to start the
+ * application. Navigating to the application URL shows the main window (
+ * {@link #getMainWindow()}) of the application. Note that the main window
+ * can also be shown by navigating to the window url (
+ * {@link com.vaadin.ui.Window#getURL()}).
+ * </p>
+ *
+ * @return the application's URL.
+ */
+ public URL getURL() {
+ return applicationUrl;
+ }
+
+ /**
+ * Ends the Application.
+ * <p>
+ * In effect this will cause the application stop returning any windows when
+ * asked. When the application is closed, close events are fired for its
+ * UIs, its state is removed from the 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.
+ */
+ public void close() {
+ applicationIsRunning = false;
+ for (UI ui : getUIs()) {
+ ui.fireCloseEvent();
+ }
+ }
+
+ public static VaadinSession getForSession(WrappedSession session) {
+ Object attribute = session.getAttribute(VaadinSession.class.getName());
+ if (attribute instanceof VaadinSession) {
+ VaadinSession application = (VaadinSession) attribute;
+ application.session = session;
+ return application;
+ }
+
+ return null;
+ }
+
+ public void removeFromSession() {
+ assert (getForSession(session) == this);
+
+ session.setAttribute(VaadinSession.class.getName(), null);
+ }
+
+ public void storeInSession(WrappedSession session) {
+ session.setAttribute(VaadinSession.class.getName(), this);
+ this.session = session;
+ }
+
+ /**
+ * Starts the application on the given URL.
+ *
+ * <p>
+ * This method is called by Vaadin framework when a user navigates to the
+ * application. After this call the application corresponds to the given URL
+ * and it will return windows when asked for them. There is no need to call
+ * this method directly.
+ * </p>
+ *
+ * <p>
+ * Application properties are defined by servlet configuration object
+ * {@link javax.servlet.ServletConfig} and they are overridden by
+ * context-wide initialization parameters
+ * {@link javax.servlet.ServletContext}.
+ * </p>
+ *
+ * @param event
+ * the application start event containing details required for
+ * starting the application.
+ *
+ */
+ public void start(ApplicationStartEvent event) {
+ 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(ApplicationStartEvent)}
+ * 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.
+ */
+ public boolean isRunning() {
+ return applicationIsRunning;
+ }
+
+ /**
+ * Gets the configuration for this application
+ *
+ * @return the application configuration
+ */
+ public ApplicationConfiguration getConfiguration() {
+ return configuration;
+ }
+
+ /**
+ * Gets the default locale for this application.
+ *
+ * By default this is the preferred locale of the user using the
+ * application. In most cases it is read from the browser defaults.
+ *
+ * @return the locale of this application.
+ */
+ public Locale getLocale() {
+ if (locale != null) {
+ return locale;
+ }
+ return Locale.getDefault();
+ }
+
+ /**
+ * Sets the default locale for this application.
+ *
+ * By default this is the preferred locale of the user using the
+ * application. In most cases it is read from the browser defaults.
+ *
+ * @param locale
+ * the Locale object.
+ *
+ */
+ public void setLocale(Locale locale) {
+ this.locale = locale;
+ }
+
+ /**
+ * Window detach event.
+ *
+ * This event is sent each time a window is removed from the application
+ * with {@link com.vaadin.server.VaadinSession#removeWindow(Window)}.
+ */
+ public static class WindowDetachEvent extends EventObject {
+
+ private final Window window;
+
+ /**
+ * Creates a event.
+ *
+ * @param application
+ * the application to which the detached window belonged.
+ * @param window
+ * the Detached window.
+ */
+ public WindowDetachEvent(VaadinSession application, Window window) {
+ super(application);
+ this.window = window;
+ }
+
+ /**
+ * Gets the detached window.
+ *
+ * @return the detached window.
+ */
+ public Window getWindow() {
+ return window;
+ }
+
+ /**
+ * Gets the application from which the window was detached.
+ *
+ * @return the Application.
+ */
+ public VaadinSession getApplication() {
+ return (VaadinSession) getSource();
+ }
+ }
+
+ /**
+ * Window attach event.
+ *
+ * This event is sent each time a window is attached tothe application with
+ * {@link com.vaadin.server.VaadinSession#addWindow(Window)}.
+ */
+ public static class WindowAttachEvent extends EventObject {
+
+ private final Window window;
+
+ /**
+ * Creates a event.
+ *
+ * @param application
+ * the application to which the detached window belonged.
+ * @param window
+ * the Attached window.
+ */
+ public WindowAttachEvent(VaadinSession application, Window window) {
+ super(application);
+ this.window = window;
+ }
+
+ /**
+ * Gets the attached window.
+ *
+ * @return the attached window.
+ */
+ public Window getWindow() {
+ return window;
+ }
+
+ /**
+ * Gets the application to which the window was attached.
+ *
+ * @return the Application.
+ */
+ public VaadinSession getApplication() {
+ return (VaadinSession) getSource();
+ }
+ }
+
+ /**
+ * Window attach listener interface.
+ */
+ public interface WindowAttachListener extends Serializable {
+
+ /**
+ * Window attached
+ *
+ * @param event
+ * the window attach event.
+ */
+ public void windowAttached(WindowAttachEvent event);
+ }
+
+ /**
+ * Window detach listener interface.
+ */
+ public interface WindowDetachListener extends Serializable {
+
+ /**
+ * Window detached.
+ *
+ * @param event
+ * the window detach event.
+ */
+ 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.
+ */
+ 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.
+ */
+ public void setLogoutURL(String logoutURL) {
+ this.logoutURL = logoutURL;
+ }
+
+ /**
+ * <p>
+ * Invoked by the terminal on any exception that occurs in application and
+ * is thrown by the <code>setVariable</code> to the terminal. The default
+ * implementation sets the exceptions as <code>ComponentErrors</code> to the
+ * component that initiated the exception and prints stack trace to standard
+ * error stream.
+ * </p>
+ * <p>
+ * You can safely override this method in your application in order to
+ * direct the errors to some other destination (for example log).
+ * </p>
+ *
+ * @param event
+ * the change event.
+ * @see com.vaadin.server.Terminal.ErrorListener#terminalError(com.vaadin.server.Terminal.ErrorEvent)
+ */
+
+ @Override
+ public void terminalError(Terminal.ErrorEvent event) {
+ final Throwable t = event.getThrowable();
+ if (t instanceof SocketException) {
+ // Most likely client browser closed socket
+ getLogger().info(
+ "SocketException in CommunicationManager."
+ + " Most likely client (browser) closed socket.");
+ return;
+ }
+
+ // Finds the original source of the error/exception
+ Object owner = null;
+ if (event instanceof VariableOwner.ErrorEvent) {
+ owner = ((VariableOwner.ErrorEvent) event).getVariableOwner();
+ } else if (event instanceof ChangeVariablesErrorEvent) {
+ owner = ((ChangeVariablesErrorEvent) event).getComponent();
+ }
+
+ // Shows the error in AbstractComponent
+ if (owner instanceof AbstractComponent) {
+ ((AbstractComponent) owner).setComponentError(AbstractErrorMessage
+ .getErrorMessageForException(t));
+ }
+
+ // also print the error on console
+ getLogger().log(Level.SEVERE, "Terminal error:", t);
+ }
+
+ /**
+ * Gets the application error handler.
+ *
+ * The default error handler is the application itself.
+ *
+ * @return Application error handler
+ */
+ public Terminal.ErrorListener getErrorHandler() {
+ return errorHandler;
+ }
+
+ /**
+ * Sets the application error handler.
+ *
+ * The default error handler is the application itself. By overriding this,
+ * you can redirect the error messages to your selected target (log for
+ * example).
+ *
+ * @param errorHandler
+ */
+ public void setErrorHandler(Terminal.ErrorListener errorHandler) {
+ this.errorHandler = errorHandler;
+ }
+
+ /**
+ * Gets the {@link ConverterFactory} used to locate a suitable
+ * {@link Converter} for fields in the application.
+ *
+ * See {@link #setConverterFactory(ConverterFactory)} for more details
+ *
+ * @return The converter factory used in the application
+ */
+ public ConverterFactory getConverterFactory() {
+ return converterFactory;
+ }
+
+ /**
+ * Sets the {@link ConverterFactory} used to locate a suitable
+ * {@link Converter} for fields in the application.
+ * <p>
+ * The {@link ConverterFactory} is used to find a suitable converter when
+ * binding data to a UI component and the data type does not match the UI
+ * component type, e.g. binding a Double to a TextField (which is based on a
+ * String).
+ * </p>
+ * <p>
+ * The {@link Converter} for an individual field can be overridden using
+ * {@link AbstractField#setConverter(Converter)} and for individual property
+ * ids in a {@link Table} using
+ * {@link Table#setConverter(Object, Converter)}.
+ * </p>
+ * <p>
+ * The converter factory must never be set to null.
+ *
+ * @param converterFactory
+ * The converter factory used in the application
+ */
+ public void setConverterFactory(ConverterFactory converterFactory) {
+ this.converterFactory = converterFactory;
+ }
+
+ /**
+ * Contains the system messages used to notify the user about various
+ * critical situations that can occur.
+ * <p>
+ * Customize by overriding the static
+ * {@link VaadinSession#getSystemMessages()} and returning
+ * {@link CustomizedSystemMessages}.
+ * </p>
+ * <p>
+ * The defaults defined in this class are:
+ * <ul>
+ * <li><b>sessionExpiredURL</b> = null</li>
+ * <li><b>sessionExpiredNotificationEnabled</b> = true</li>
+ * <li><b>sessionExpiredCaption</b> = ""</li>
+ * <li><b>sessionExpiredMessage</b> =
+ * "Take note of any unsaved data, and <u>click here</u> to continue."</li>
+ * <li><b>communicationErrorURL</b> = null</li>
+ * <li><b>communicationErrorNotificationEnabled</b> = true</li>
+ * <li><b>communicationErrorCaption</b> = "Communication problem"</li>
+ * <li><b>communicationErrorMessage</b> =
+ * "Take note of any unsaved data, and <u>click here</u> to continue."</li>
+ * <li><b>internalErrorURL</b> = null</li>
+ * <li><b>internalErrorNotificationEnabled</b> = true</li>
+ * <li><b>internalErrorCaption</b> = "Internal error"</li>
+ * <li><b>internalErrorMessage</b> = "Please notify the administrator.<br/>
+ * Take note of any unsaved data, and <u>click here</u> to continue."</li>
+ * <li><b>outOfSyncURL</b> = null</li>
+ * <li><b>outOfSyncNotificationEnabled</b> = true</li>
+ * <li><b>outOfSyncCaption</b> = "Out of sync"</li>
+ * <li><b>outOfSyncMessage</b> = "Something has caused us to be out of sync
+ * with the server.<br/>
+ * Take note of any unsaved data, and <u>click here</u> to re-sync."</li>
+ * <li><b>cookiesDisabledURL</b> = null</li>
+ * <li><b>cookiesDisabledNotificationEnabled</b> = true</li>
+ * <li><b>cookiesDisabledCaption</b> = "Cookies disabled"</li>
+ * <li><b>cookiesDisabledMessage</b> = "This application requires cookies to
+ * function.<br/>
+ * Please enable cookies in your browser and <u>click here</u> to try again.
+ * </li>
+ * </ul>
+ * </p>
+ *
+ */
+ public static class SystemMessages implements Serializable {
+ protected String sessionExpiredURL = null;
+ protected boolean sessionExpiredNotificationEnabled = true;
+ protected String sessionExpiredCaption = "Session Expired";
+ protected String sessionExpiredMessage = "Take note of any unsaved data, and <u>click here</u> to continue.";
+
+ protected String communicationErrorURL = null;
+ protected boolean communicationErrorNotificationEnabled = true;
+ protected String communicationErrorCaption = "Communication problem";
+ protected String communicationErrorMessage = "Take note of any unsaved data, and <u>click here</u> to continue.";
+
+ protected String authenticationErrorURL = null;
+ protected boolean authenticationErrorNotificationEnabled = true;
+ protected String authenticationErrorCaption = "Authentication problem";
+ protected String authenticationErrorMessage = "Take note of any unsaved data, and <u>click here</u> to continue.";
+
+ protected String internalErrorURL = null;
+ protected boolean internalErrorNotificationEnabled = true;
+ protected String internalErrorCaption = "Internal error";
+ protected String internalErrorMessage = "Please notify the administrator.<br/>Take note of any unsaved data, and <u>click here</u> to continue.";
+
+ protected String outOfSyncURL = null;
+ protected boolean outOfSyncNotificationEnabled = true;
+ protected String outOfSyncCaption = "Out of sync";
+ protected String outOfSyncMessage = "Something has caused us to be out of sync with the server.<br/>Take note of any unsaved data, and <u>click here</u> to re-sync.";
+
+ protected String cookiesDisabledURL = null;
+ protected boolean cookiesDisabledNotificationEnabled = true;
+ protected String cookiesDisabledCaption = "Cookies disabled";
+ protected String cookiesDisabledMessage = "This application requires cookies to function.<br/>Please enable cookies in your browser and <u>click here</u> to try again.";
+
+ /**
+ * Use {@link CustomizedSystemMessages} to customize
+ */
+ private SystemMessages() {
+
+ }
+
+ /**
+ * @return null to indicate that the application will be restarted after
+ * session expired message has been shown.
+ */
+ public String getSessionExpiredURL() {
+ return sessionExpiredURL;
+ }
+
+ /**
+ * @return true to show session expiration message.
+ */
+ public boolean isSessionExpiredNotificationEnabled() {
+ return sessionExpiredNotificationEnabled;
+ }
+
+ /**
+ * @return "" to show no caption.
+ */
+ public String getSessionExpiredCaption() {
+ return (sessionExpiredNotificationEnabled ? sessionExpiredCaption
+ : null);
+ }
+
+ /**
+ * @return
+ * "Take note of any unsaved data, and <u>click here</u> to continue."
+ */
+ public String getSessionExpiredMessage() {
+ return (sessionExpiredNotificationEnabled ? sessionExpiredMessage
+ : null);
+ }
+
+ /**
+ * @return null to reload the application after communication error
+ * message.
+ */
+ public String getCommunicationErrorURL() {
+ return communicationErrorURL;
+ }
+
+ /**
+ * @return true to show the communication error message.
+ */
+ public boolean isCommunicationErrorNotificationEnabled() {
+ return communicationErrorNotificationEnabled;
+ }
+
+ /**
+ * @return "Communication problem"
+ */
+ public String getCommunicationErrorCaption() {
+ return (communicationErrorNotificationEnabled ? communicationErrorCaption
+ : null);
+ }
+
+ /**
+ * @return
+ * "Take note of any unsaved data, and <u>click here</u> to continue."
+ */
+ public String getCommunicationErrorMessage() {
+ return (communicationErrorNotificationEnabled ? communicationErrorMessage
+ : null);
+ }
+
+ /**
+ * @return null to reload the application after authentication error
+ * message.
+ */
+ public String getAuthenticationErrorURL() {
+ return authenticationErrorURL;
+ }
+
+ /**
+ * @return true to show the authentication error message.
+ */
+ public boolean isAuthenticationErrorNotificationEnabled() {
+ return authenticationErrorNotificationEnabled;
+ }
+
+ /**
+ * @return "Authentication problem"
+ */
+ public String getAuthenticationErrorCaption() {
+ return (authenticationErrorNotificationEnabled ? authenticationErrorCaption
+ : null);
+ }
+
+ /**
+ * @return
+ * "Take note of any unsaved data, and <u>click here</u> to continue."
+ */
+ public String getAuthenticationErrorMessage() {
+ return (authenticationErrorNotificationEnabled ? authenticationErrorMessage
+ : null);
+ }
+
+ /**
+ * @return null to reload the current URL after internal error message
+ * has been shown.
+ */
+ public String getInternalErrorURL() {
+ return internalErrorURL;
+ }
+
+ /**
+ * @return true to enable showing of internal error message.
+ */
+ public boolean isInternalErrorNotificationEnabled() {
+ return internalErrorNotificationEnabled;
+ }
+
+ /**
+ * @return "Internal error"
+ */
+ public String getInternalErrorCaption() {
+ return (internalErrorNotificationEnabled ? internalErrorCaption
+ : null);
+ }
+
+ /**
+ * @return "Please notify the administrator.<br/>
+ * Take note of any unsaved data, and <u>click here</u> to
+ * continue."
+ */
+ public String getInternalErrorMessage() {
+ return (internalErrorNotificationEnabled ? internalErrorMessage
+ : null);
+ }
+
+ /**
+ * @return null to reload the application after out of sync message.
+ */
+ public String getOutOfSyncURL() {
+ return outOfSyncURL;
+ }
+
+ /**
+ * @return true to enable showing out of sync message
+ */
+ public boolean isOutOfSyncNotificationEnabled() {
+ return outOfSyncNotificationEnabled;
+ }
+
+ /**
+ * @return "Out of sync"
+ */
+ public String getOutOfSyncCaption() {
+ return (outOfSyncNotificationEnabled ? outOfSyncCaption : null);
+ }
+
+ /**
+ * @return "Something has caused us to be out of sync with the server.<br/>
+ * Take note of any unsaved data, and <u>click here</u> to
+ * re-sync."
+ */
+ public String getOutOfSyncMessage() {
+ return (outOfSyncNotificationEnabled ? outOfSyncMessage : null);
+ }
+
+ /**
+ * Returns the URL the user should be redirected to after dismissing the
+ * "you have to enable your cookies" message. Typically null.
+ *
+ * @return A URL the user should be redirected to after dismissing the
+ * message or null to reload the current URL.
+ */
+ public String getCookiesDisabledURL() {
+ return cookiesDisabledURL;
+ }
+
+ /**
+ * Determines if "cookies disabled" messages should be shown to the end
+ * user or not. If the notification is disabled the user will be
+ * immediately redirected to the URL returned by
+ * {@link #getCookiesDisabledURL()}.
+ *
+ * @return true to show "cookies disabled" messages to the end user,
+ * false to redirect to the given URL directly
+ */
+ public boolean isCookiesDisabledNotificationEnabled() {
+ return cookiesDisabledNotificationEnabled;
+ }
+
+ /**
+ * Returns the caption of the message shown to the user when cookies are
+ * disabled in the browser.
+ *
+ * @return The caption of the "cookies disabled" message
+ */
+ public String getCookiesDisabledCaption() {
+ return (cookiesDisabledNotificationEnabled ? cookiesDisabledCaption
+ : null);
+ }
+
+ /**
+ * Returns the message shown to the user when cookies are disabled in
+ * the browser.
+ *
+ * @return The "cookies disabled" message
+ */
+ public String getCookiesDisabledMessage() {
+ return (cookiesDisabledNotificationEnabled ? cookiesDisabledMessage
+ : null);
+ }
+
+ }
+
+ /**
+ * Contains the system messages used to notify the user about various
+ * critical situations that can occur.
+ * <p>
+ * Vaadin gets the SystemMessages from your application by calling a static
+ * getSystemMessages() method. By default the
+ * Application.getSystemMessages() is used. You can customize this by
+ * defining a static MyApplication.getSystemMessages() and returning
+ * CustomizedSystemMessages. Note that getSystemMessages() is static -
+ * changing the system messages will by default change the message for all
+ * users of the application.
+ * </p>
+ * <p>
+ * The default behavior is to show a notification, and restart the
+ * application the the user clicks the message. <br/>
+ * Instead of restarting the application, you can set a specific URL that
+ * the user is taken to.<br/>
+ * Setting both caption and message to null will restart the application (or
+ * go to the specified URL) without displaying a notification.
+ * set*NotificationEnabled(false) will achieve the same thing.
+ * </p>
+ * <p>
+ * The situations are:
+ * <li>Session expired: the user session has expired, usually due to
+ * inactivity.</li>
+ * <li>Communication error: the client failed to contact the server, or the
+ * server returned and invalid response.</li>
+ * <li>Internal error: unhandled critical server error (e.g out of memory,
+ * database crash)
+ * <li>Out of sync: the client is not in sync with the server. E.g the user
+ * opens two windows showing the same application, but the application does
+ * not support this and uses the same Window instance. When the user makes
+ * changes in one of the windows - the other window is no longer in sync,
+ * and (for instance) pressing a button that is no longer present in the UI
+ * will cause a out-of-sync -situation.
+ * </p>
+ */
+
+ public static class CustomizedSystemMessages extends SystemMessages
+ implements Serializable {
+
+ /**
+ * Sets the URL to go to when the session has expired.
+ *
+ * @param sessionExpiredURL
+ * the URL to go to, or null to reload current
+ */
+ public void setSessionExpiredURL(String sessionExpiredURL) {
+ this.sessionExpiredURL = sessionExpiredURL;
+ }
+
+ /**
+ * Enables or disables the notification. If disabled, the set URL (or
+ * current) is loaded directly when next transaction between server and
+ * client happens.
+ *
+ * @param sessionExpiredNotificationEnabled
+ * true = enabled, false = disabled
+ */
+ public void setSessionExpiredNotificationEnabled(
+ boolean sessionExpiredNotificationEnabled) {
+ this.sessionExpiredNotificationEnabled = sessionExpiredNotificationEnabled;
+ }
+
+ /**
+ * Sets the caption of the notification. Set to null for no caption. If
+ * both caption and message are null, client automatically forwards to
+ * sessionExpiredUrl after timeout timer expires. Timer uses value read
+ * from HTTPSession.getMaxInactiveInterval()
+ *
+ * @param sessionExpiredCaption
+ * the caption
+ */
+ public void setSessionExpiredCaption(String sessionExpiredCaption) {
+ this.sessionExpiredCaption = sessionExpiredCaption;
+ }
+
+ /**
+ * Sets the message of the notification. Set to null for no message. If
+ * both caption and message are null, client automatically forwards to
+ * sessionExpiredUrl after timeout timer expires. Timer uses value read
+ * from HTTPSession.getMaxInactiveInterval()
+ *
+ * @param sessionExpiredMessage
+ * the message
+ */
+ public void setSessionExpiredMessage(String sessionExpiredMessage) {
+ this.sessionExpiredMessage = sessionExpiredMessage;
+ }
+
+ /**
+ * Sets the URL to go to when there is a authentication error.
+ *
+ * @param authenticationErrorURL
+ * the URL to go to, or null to reload current
+ */
+ public void setAuthenticationErrorURL(String authenticationErrorURL) {
+ this.authenticationErrorURL = authenticationErrorURL;
+ }
+
+ /**
+ * Enables or disables the notification. If disabled, the set URL (or
+ * current) is loaded directly.
+ *
+ * @param authenticationErrorNotificationEnabled
+ * true = enabled, false = disabled
+ */
+ public void setAuthenticationErrorNotificationEnabled(
+ boolean authenticationErrorNotificationEnabled) {
+ this.authenticationErrorNotificationEnabled = authenticationErrorNotificationEnabled;
+ }
+
+ /**
+ * Sets the caption of the notification. Set to null for no caption. If
+ * both caption and message is null, the notification is disabled;
+ *
+ * @param authenticationErrorCaption
+ * the caption
+ */
+ public void setAuthenticationErrorCaption(
+ String authenticationErrorCaption) {
+ this.authenticationErrorCaption = authenticationErrorCaption;
+ }
+
+ /**
+ * Sets the message of the notification. Set to null for no message. If
+ * both caption and message is null, the notification is disabled;
+ *
+ * @param authenticationErrorMessage
+ * the message
+ */
+ public void setAuthenticationErrorMessage(
+ String authenticationErrorMessage) {
+ this.authenticationErrorMessage = authenticationErrorMessage;
+ }
+
+ /**
+ * Sets the URL to go to when there is a communication error.
+ *
+ * @param communicationErrorURL
+ * the URL to go to, or null to reload current
+ */
+ public void setCommunicationErrorURL(String communicationErrorURL) {
+ this.communicationErrorURL = communicationErrorURL;
+ }
+
+ /**
+ * Enables or disables the notification. If disabled, the set URL (or
+ * current) is loaded directly.
+ *
+ * @param communicationErrorNotificationEnabled
+ * true = enabled, false = disabled
+ */
+ public void setCommunicationErrorNotificationEnabled(
+ boolean communicationErrorNotificationEnabled) {
+ this.communicationErrorNotificationEnabled = communicationErrorNotificationEnabled;
+ }
+
+ /**
+ * Sets the caption of the notification. Set to null for no caption. If
+ * both caption and message is null, the notification is disabled;
+ *
+ * @param communicationErrorCaption
+ * the caption
+ */
+ public void setCommunicationErrorCaption(
+ String communicationErrorCaption) {
+ this.communicationErrorCaption = communicationErrorCaption;
+ }
+
+ /**
+ * Sets the message of the notification. Set to null for no message. If
+ * both caption and message is null, the notification is disabled;
+ *
+ * @param communicationErrorMessage
+ * the message
+ */
+ public void setCommunicationErrorMessage(
+ String communicationErrorMessage) {
+ this.communicationErrorMessage = communicationErrorMessage;
+ }
+
+ /**
+ * Sets the URL to go to when an internal error occurs.
+ *
+ * @param internalErrorURL
+ * the URL to go to, or null to reload current
+ */
+ public void setInternalErrorURL(String internalErrorURL) {
+ this.internalErrorURL = internalErrorURL;
+ }
+
+ /**
+ * Enables or disables the notification. If disabled, the set URL (or
+ * current) is loaded directly.
+ *
+ * @param internalErrorNotificationEnabled
+ * true = enabled, false = disabled
+ */
+ public void setInternalErrorNotificationEnabled(
+ boolean internalErrorNotificationEnabled) {
+ this.internalErrorNotificationEnabled = internalErrorNotificationEnabled;
+ }
+
+ /**
+ * Sets the caption of the notification. Set to null for no caption. If
+ * both caption and message is null, the notification is disabled;
+ *
+ * @param internalErrorCaption
+ * the caption
+ */
+ public void setInternalErrorCaption(String internalErrorCaption) {
+ this.internalErrorCaption = internalErrorCaption;
+ }
+
+ /**
+ * Sets the message of the notification. Set to null for no message. If
+ * both caption and message is null, the notification is disabled;
+ *
+ * @param internalErrorMessage
+ * the message
+ */
+ public void setInternalErrorMessage(String internalErrorMessage) {
+ this.internalErrorMessage = internalErrorMessage;
+ }
+
+ /**
+ * Sets the URL to go to when the client is out-of-sync.
+ *
+ * @param outOfSyncURL
+ * the URL to go to, or null to reload current
+ */
+ public void setOutOfSyncURL(String outOfSyncURL) {
+ this.outOfSyncURL = outOfSyncURL;
+ }
+
+ /**
+ * Enables or disables the notification. If disabled, the set URL (or
+ * current) is loaded directly.
+ *
+ * @param outOfSyncNotificationEnabled
+ * true = enabled, false = disabled
+ */
+ public void setOutOfSyncNotificationEnabled(
+ boolean outOfSyncNotificationEnabled) {
+ this.outOfSyncNotificationEnabled = outOfSyncNotificationEnabled;
+ }
+
+ /**
+ * Sets the caption of the notification. Set to null for no caption. If
+ * both caption and message is null, the notification is disabled;
+ *
+ * @param outOfSyncCaption
+ * the caption
+ */
+ public void setOutOfSyncCaption(String outOfSyncCaption) {
+ this.outOfSyncCaption = outOfSyncCaption;
+ }
+
+ /**
+ * Sets the message of the notification. Set to null for no message. If
+ * both caption and message is null, the notification is disabled;
+ *
+ * @param outOfSyncMessage
+ * the message
+ */
+ public void setOutOfSyncMessage(String outOfSyncMessage) {
+ this.outOfSyncMessage = outOfSyncMessage;
+ }
+
+ /**
+ * Sets the URL to redirect to when the browser has cookies disabled.
+ *
+ * @param cookiesDisabledURL
+ * the URL to redirect to, or null to reload the current URL
+ */
+ public void setCookiesDisabledURL(String cookiesDisabledURL) {
+ this.cookiesDisabledURL = cookiesDisabledURL;
+ }
+
+ /**
+ * Enables or disables the notification for "cookies disabled" messages.
+ * If disabled, the URL returned by {@link #getCookiesDisabledURL()} is
+ * loaded directly.
+ *
+ * @param cookiesDisabledNotificationEnabled
+ * true to enable "cookies disabled" messages, false
+ * otherwise
+ */
+ public void setCookiesDisabledNotificationEnabled(
+ boolean cookiesDisabledNotificationEnabled) {
+ this.cookiesDisabledNotificationEnabled = cookiesDisabledNotificationEnabled;
+ }
+
+ /**
+ * Sets the caption of the "cookies disabled" notification. Set to null
+ * for no caption. If both caption and message is null, the notification
+ * is disabled.
+ *
+ * @param cookiesDisabledCaption
+ * the caption for the "cookies disabled" notification
+ */
+ public void setCookiesDisabledCaption(String cookiesDisabledCaption) {
+ this.cookiesDisabledCaption = cookiesDisabledCaption;
+ }
+
+ /**
+ * Sets the message of the "cookies disabled" notification. Set to null
+ * for no message. If both caption and message is null, the notification
+ * is disabled.
+ *
+ * @param cookiesDisabledMessage
+ * the message for the "cookies disabled" notification
+ */
+ public void setCookiesDisabledMessage(String cookiesDisabledMessage) {
+ this.cookiesDisabledMessage = cookiesDisabledMessage;
+ }
+
+ }
+
+ /**
+ * Application error is an error message defined on the application level.
+ *
+ * When an error occurs on the application level, this error message type
+ * should be used. This indicates that the problem is caused by the
+ * application - not by the user.
+ */
+ public class ApplicationError implements Terminal.ErrorEvent {
+ private final Throwable throwable;
+
+ public ApplicationError(Throwable throwable) {
+ this.throwable = throwable;
+ }
+
+ @Override
+ public Throwable getThrowable() {
+ return throwable;
+ }
+
+ }
+
+ /**
+ * Gets the UI class for a request for which no UI is already known. This
+ * method is called when the framework processes a request that does not
+ * originate from an existing UI instance. This typically happens when a
+ * host page is requested.
+ * <p>
+ * Subclasses of Application may override this method to provide custom
+ * logic for choosing what kind of UI to use.
+ * <p>
+ * The default implementation in {@link VaadinSession} uses the
+ * {@value #UI_PARAMETER} parameter from web.xml for finding the name of the
+ * UI class. If {@link DeploymentConfiguration#getClassLoader()} does not
+ * return <code>null</code>, the returned {@link ClassLoader} is used for
+ * loading the UI class. Otherwise the {@link ClassLoader} used to load this
+ * class is used.
+ *
+ * </p>
+ *
+ * @param request
+ * the wrapped request for which a UI is needed
+ * @return a UI instance to use for the request
+ *
+ * @see UI
+ * @see WrappedRequest#getBrowserDetails()
+ *
+ * @since 7.0
+ */
+ public Class<? extends UI> getUIClass(WrappedRequest request) {
+ UIProvider uiProvider = getUiProvider(request, null);
+ return uiProvider.getUIClass(this, request);
+ }
+
+ /**
+ * Creates an UI instance for a request for which no UI is already known.
+ * This method is called when the framework processes a request that does
+ * not originate from an existing UI instance. This typically happens when a
+ * host page is requested.
+ * <p>
+ * Subclasses of Application may override this method to provide custom
+ * logic for choosing how to create a suitable UI or for picking an already
+ * created UI. If an existing UI is picked, care should be taken to avoid
+ * keeping the same UI open in multiple browser windows, as that will cause
+ * the states to go out of sync.
+ * </p>
+ *
+ * @param request
+ * @param uiClass
+ * @return
+ */
+ protected <T extends UI> T createUIInstance(WrappedRequest request,
+ Class<T> uiClass) {
+ UIProvider uiProvider = getUiProvider(request, uiClass);
+ return uiClass.cast(uiProvider.createInstance(this, uiClass, request));
+ }
+
+ /**
+ * Gets the {@link UIProvider} that should be used for a request. The
+ * selection can further be restricted by also requiring the UI provider to
+ * support a specific UI class.
+ *
+ * @see UIProvider
+ * @see #addUIProvider(UIProvider)
+ *
+ * @param request
+ * the request for which to get an UI provider
+ * @param uiClass
+ * the UI class for which a provider is required, or
+ * <code>null</code> to use the first UI provider supporting the
+ * request.
+ * @return an UI provider supporting the request (and the UI class if
+ * provided).
+ *
+ * @since 7.0.0
+ */
+ public UIProvider getUiProvider(WrappedRequest request, Class<?> uiClass) {
+ UIProvider provider = (UIProvider) request
+ .getAttribute(UIProvider.class.getName());
+ if (provider != null) {
+ // Cached provider found, verify that it's a sensible selection
+ Class<? extends UI> providerClass = provider.getUIClass(this,
+ request);
+ if (uiClass == null && providerClass != null) {
+ // Use it if it gives any answer if no specific class is
+ // required
+ return provider;
+ } else if (uiClass == providerClass) {
+ // Use it if it gives the expected UI class
+ return provider;
+ } else {
+ // Don't keep it cached if it doesn't match the expectations
+ request.setAttribute(UIProvider.class.getName(), null);
+ }
+ }
+
+ // Iterate all current providers if no matching cached provider found
+ provider = doGetUiProvider(request, uiClass);
+
+ // Cache the found provider
+ request.setAttribute(UIProvider.class.getName(), provider);
+
+ return provider;
+ }
+
+ private UIProvider doGetUiProvider(WrappedRequest request, Class<?> uiClass) {
+ int providersSize = uiProviders.size();
+ if (providersSize == 0) {
+ throw new IllegalStateException("There are no UI providers");
+ }
+
+ for (int i = providersSize - 1; i >= 0; i--) {
+ UIProvider provider = uiProviders.get(i);
+
+ Class<? extends UI> providerClass = provider.getUIClass(this,
+ request);
+ // If we found something
+ if (providerClass != null) {
+ if (uiClass == null) {
+ // Not looking for anything particular -> anything is ok
+ return provider;
+ } else if (providerClass == uiClass) {
+ // Looking for a specific provider -> only use if matching
+ return provider;
+ } else {
+ getLogger().warning(
+ "Mismatching UI classes. Expected " + uiClass
+ + " but got " + providerClass + " from "
+ + provider);
+ // Continue looking
+ }
+ }
+ }
+
+ throw new RuntimeException("No UI provider found for request");
+ }
+
+ /**
+ * Handles a request by passing it to each registered {@link RequestHandler}
+ * in turn until one produces a response. This method is used for requests
+ * that have not been handled by any specific functionality in the terminal
+ * implementation (e.g. {@link VaadinServlet}).
+ * <p>
+ * The request handlers are invoked in the revere order in which they were
+ * added to the application until a response has been produced. This means
+ * that the most recently added handler is used first and the first request
+ * handler that was added to the application is invoked towards the end
+ * unless any previous handler has already produced a response.
+ * </p>
+ *
+ * @param request
+ * the wrapped request to get information from
+ * @param response
+ * the response to which data can be written
+ * @return returns <code>true</code> if a {@link RequestHandler} has
+ * produced a response and <code>false</code> if no response has
+ * been written.
+ * @throws IOException
+ *
+ * @see #addRequestHandler(RequestHandler)
+ * @see RequestHandler
+ *
+ * @since 7.0
+ */
+ public boolean handleRequest(WrappedRequest request,
+ WrappedResponse response) throws IOException {
+ // Use a copy to avoid ConcurrentModificationException
+ for (RequestHandler handler : new ArrayList<RequestHandler>(
+ requestHandlers)) {
+ if (handler.handleRequest(this, request, response)) {
+ return true;
+ }
+ }
+ // If not handled
+ return false;
+ }
+
+ /**
+ * Adds a request handler to this application. Request handlers can be added
+ * to provide responses to requests that are not handled by the default
+ * functionality of the framework.
+ * <p>
+ * Handlers are called in reverse order of addition, so the most recently
+ * added handler will be called first.
+ * </p>
+ *
+ * @param handler
+ * the request handler to add
+ *
+ * @see #handleRequest(WrappedRequest, WrappedResponse)
+ * @see #removeRequestHandler(RequestHandler)
+ *
+ * @since 7.0
+ */
+ public void addRequestHandler(RequestHandler handler) {
+ requestHandlers.addFirst(handler);
+ }
+
+ /**
+ * Removes a request handler from the application.
+ *
+ * @param handler
+ * the request handler to remove
+ *
+ * @since 7.0
+ */
+ public void removeRequestHandler(RequestHandler handler) {
+ requestHandlers.remove(handler);
+ }
+
+ /**
+ * Gets the request handlers that are registered to the application. The
+ * iteration order of the returned collection is the same as the order in
+ * which the request handlers will be invoked when a request is handled.
+ *
+ * @return a collection of request handlers, with the iteration order
+ * according to the order they would be invoked
+ *
+ * @see #handleRequest(WrappedRequest, WrappedResponse)
+ * @see #addRequestHandler(RequestHandler)
+ * @see #removeRequestHandler(RequestHandler)
+ *
+ * @since 7.0
+ */
+ public Collection<RequestHandler> getRequestHandlers() {
+ return Collections.unmodifiableCollection(requestHandlers);
+ }
+
+ /**
+ * Gets the currently used application. The current application is
+ * automatically defined when processing requests to the server. In other
+ * cases, (e.g. from background threads), the current application is not
+ * automatically defined.
+ *
+ * @return the current application instance if available, otherwise
+ * <code>null</code>
+ *
+ * @see #setCurrent(VaadinSession)
+ *
+ * @since 7.0
+ */
+ public static VaadinSession getCurrent() {
+ return CurrentInstance.get(VaadinSession.class);
+ }
+
+ /**
+ * Sets the thread local for the current application. This method is used by
+ * the framework to set the current application whenever a new request is
+ * processed and it is cleared when the request has been processed.
+ * <p>
+ * The application developer can also use this method to define the current
+ * application outside the normal request handling, e.g. when initiating
+ * custom background threads.
+ * </p>
+ *
+ * @param application
+ *
+ * @see #getCurrent()
+ * @see ThreadLocal
+ *
+ * @since 7.0
+ */
+ public static void setCurrent(VaadinSession application) {
+ CurrentInstance.setInheritable(VaadinSession.class, application);
+ }
+
+ /**
+ * Check whether this application is in production mode. If an application
+ * is in production mode, certain debugging facilities are not available.
+ *
+ * @return the status of the production mode flag
+ *
+ * @since 7.0
+ */
+ public boolean isProductionMode() {
+ return configuration.isProductionMode();
+ }
+
+ public void addUIProvider(UIProvider uIProvider) {
+ uiProviders.add(uIProvider);
+ }
+
+ public void removeUIProvider(UIProvider uIProvider) {
+ uiProviders.remove(uIProvider);
+ }
+
+ /**
+ * Finds the {@link UI} to which a particular request belongs. If the
+ * request originates from an existing UI, that UI is returned. In other
+ * cases, the method attempts to create and initialize a new UI and might
+ * throw a {@link UIRequiresMoreInformationException} if all required
+ * information is not available.
+ * <p>
+ * Please note that this method can also return a newly created
+ * <code>UI</code> which has not yet been initialized. You can use
+ * {@link #isUIInitPending(int)} with the UI's id ( {@link UI#getUIId()} to
+ * check whether the initialization is still pending.
+ * </p>
+ *
+ * @param request
+ * the request for which a UI is desired
+ * @return a UI belonging to the request
+ *
+ * @see #createUI(WrappedRequest)
+ *
+ * @since 7.0
+ */
+ public UI getUIForRequest(WrappedRequest request) {
+ UI uI = UI.getCurrent();
+ if (uI != null) {
+ return uI;
+ }
+ Integer uiId = getUIId(request);
+
+ synchronized (this) {
+ uI = uIs.get(uiId);
+
+ if (uI == null) {
+ uI = findExistingUi(request);
+ }
+
+ } // end synchronized block
+
+ UI.setCurrent(uI);
+
+ 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);
+
+ UI ui = createUIInstance(request, uiClass);
+
+ // Initialize some fields for a newly created UI
+ if (ui.getSession() == null) {
+ ui.setSession(this);
+ }
+ // Get the next id
+ Integer uiId = Integer.valueOf(nextUIId++);
+
+ uIs.put(uiId, ui);
+
+ // Set thread local here so it is available in init
+ UI.setCurrent(ui);
+
+ ui.doInit(request, uiId.intValue());
+
+ if (getUiProvider(request, uiClass).isUiPreserved(request, uiClass)) {
+ // Remember this UI
+ String windowName = request.getBrowserDetails().getWindowName();
+ if (windowName == null) {
+ getLogger().warning(
+ "There is no window.name available for UI " + uiClass
+ + " that should be preserved.");
+ } else {
+ retainOnRefreshUIs.put(windowName, uiId);
+ }
+ }
+
+ return ui;
+ }
+
+ /**
+ * Internal helper to finds the UI id for a request.
+ *
+ * @param request
+ * the request to get the UI id for
+ * @return a UI id, or <code>null</code> if no UI id is defined
+ *
+ * @since 7.0
+ */
+ private static Integer getUIId(WrappedRequest request) {
+ if (request instanceof CombinedRequest) {
+ // Combined requests has the uiId parameter in the second request
+ CombinedRequest combinedRequest = (CombinedRequest) request;
+ request = combinedRequest.getSecondRequest();
+ }
+ String uiIdString = request.getParameter(UIConstants.UI_ID_PARAMETER);
+ Integer uiId = uiIdString == null ? null : new Integer(uiIdString);
+ return uiId;
+ }
+
+ /**
+ * Gets all the uIs of this application. This includes uIs that have been
+ * requested but not yet initialized. Please note, that uIs are not
+ * automatically removed e.g. if the browser window is closed and that there
+ * is no way to manually remove a UI. Inactive uIs will thus not be released
+ * for GC until the entire application is released when the session has
+ * timed out (unless there are dangling references). Improved support for
+ * releasing unused uIs is planned for an upcoming alpha release of Vaadin
+ * 7.
+ *
+ * @return a collection of uIs belonging to this application
+ *
+ * @since 7.0
+ */
+ public Collection<UI> getUIs() {
+ return Collections.unmodifiableCollection(uIs.values());
+ }
+
+ private int connectorIdSequence = 0;
+
+ /**
+ * Generate an id for the given Connector. Connectors must not call this
+ * method more than once, the first time they need an id.
+ *
+ * @param connector
+ * A connector that has not yet been assigned an id.
+ * @return A new id for the connector
+ */
+ public String createConnectorId(ClientConnector connector) {
+ return String.valueOf(connectorIdSequence++);
+ }
+
+ private static final Logger getLogger() {
+ return Logger.getLogger(VaadinSession.class.getName());
+ }
+
+ /**
+ * Returns a UI with the given id.
+ * <p>
+ * This is meant for framework internal use.
+ * </p>
+ *
+ * @param uiId
+ * The UI id
+ * @return The UI with the given id or null if not found
+ */
+ public UI getUIById(int uiId) {
+ return uIs.get(uiId);
+ }
+
+ /**
+ * Adds a listener that will be invoked when the bootstrap HTML is about to
+ * be generated. This can be used to modify the contents of the HTML that
+ * loads the Vaadin application in the browser and the HTTP headers that are
+ * included in the response serving the HTML.
+ *
+ * @see BootstrapListener#modifyBootstrapFragment(BootstrapFragmentResponse)
+ * @see BootstrapListener#modifyBootstrapPage(BootstrapPageResponse)
+ *
+ * @param listener
+ * the bootstrap listener to add
+ */
+ public void addBootstrapListener(BootstrapListener listener) {
+ eventRouter.addListener(BootstrapFragmentResponse.class, listener,
+ BOOTSTRAP_FRAGMENT_METHOD);
+ eventRouter.addListener(BootstrapPageResponse.class, listener,
+ BOOTSTRAP_PAGE_METHOD);
+ }
+
+ /**
+ * Remove a bootstrap listener that was previously added.
+ *
+ * @see #addBootstrapListener(BootstrapListener)
+ *
+ * @param listener
+ * the bootstrap listener to remove
+ */
+ public void removeBootstrapListener(BootstrapListener listener) {
+ eventRouter.removeListener(BootstrapFragmentResponse.class, listener,
+ BOOTSTRAP_FRAGMENT_METHOD);
+ eventRouter.removeListener(BootstrapPageResponse.class, listener,
+ BOOTSTRAP_PAGE_METHOD);
+ }
+
+ /**
+ * Fires a bootstrap event to all registered listeners. There are currently
+ * two supported events, both inheriting from {@link BootstrapResponse}:
+ * {@link BootstrapFragmentResponse} and {@link BootstrapPageResponse}.
+ *
+ * @param response
+ * the bootstrap response event for which listeners should be
+ * fired
+ */
+ public void modifyBootstrapResponse(BootstrapResponse response) {
+ eventRouter.fireEvent(response);
+ }
+
+ /**
+ * Removes all those UIs from the application for which {@link #isUIAlive}
+ * returns false. Close events are fired for the removed UIs.
+ * <p>
+ * Called by the framework at the end of every request.
+ *
+ * @see UI.CloseEvent
+ * @see UI.CloseListener
+ * @see #isUIAlive(UI)
+ *
+ * @since 7.0.0
+ */
+ public void closeInactiveUIs() {
+ for (Iterator<UI> i = uIs.values().iterator(); i.hasNext();) {
+ UI ui = i.next();
+ if (!isUIAlive(ui)) {
+ i.remove();
+ retainOnRefreshUIs.values().remove(ui.getUIId());
+ ui.fireCloseEvent();
+ getLogger().info(
+ "Closed UI #" + ui.getUIId() + " due to inactivity");
+ }
+ }
+ }
+
+ /**
+ * 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
+ * application. This is a lower bound; it might take longer to close an
+ * inactive UI. Returns a negative number if heartbeat is disabled and
+ * timeout never occurs.
+ *
+ * @see #getUidlRequestTimeout()
+ * @see #closeInactiveUIs()
+ * @see DeploymentConfiguration#getHeartbeatInterval()
+ *
+ * @since 7.0.0
+ *
+ * @return The heartbeat timeout in seconds or a negative number if timeout
+ * never occurs.
+ */
+ protected int getHeartbeatTimeout() {
+ // Permit three missed heartbeats before closing the UI
+ return (int) (configuration.getHeartbeatInterval() * (3.1));
+ }
+
+ /**
+ * Returns the number of seconds that must pass without a valid UIDL request
+ * being received from a UI before the UI is removed from the application,
+ * even though heartbeat requests are received. This is a lower bound; it
+ * might take longer to close an inactive UI. Returns a negative number if
+ * <p>
+ * This timeout only has effect if cleanup of inactive UIs is enabled;
+ * otherwise heartbeat requests are enough to extend UI lifetime
+ * indefinitely.
+ *
+ * @see DeploymentConfiguration#isIdleUICleanupEnabled()
+ * @see #getHeartbeatTimeout()
+ * @see #closeInactiveUIs()
+ *
+ * @since 7.0.0
+ *
+ * @return The UIDL request timeout in seconds, or a negative number if
+ * timeout never occurs.
+ */
+ protected int getUidlRequestTimeout() {
+ return configuration.isIdleUICleanupEnabled() ? getSession()
+ .getMaxInactiveInterval() : -1;
+ }
+
+ /**
+ * Returns whether the given UI is alive (the client-side actively
+ * communicates with the server) or whether it can be removed from the
+ * application and eventually collected.
+ *
+ * @since 7.0.0
+ *
+ * @param ui
+ * The UI whose status to check
+ * @return true if the UI is alive, false if it could be removed.
+ */
+ protected boolean isUIAlive(UI ui) {
+ long now = System.currentTimeMillis();
+ if (getHeartbeatTimeout() >= 0
+ && now - ui.getLastHeartbeatTime() > 1000 * getHeartbeatTimeout()) {
+ return false;
+ }
+ if (getUidlRequestTimeout() >= 0
+ && now - ui.getLastUidlRequestTime() > 1000 * getUidlRequestTimeout()) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Gets this application's global resource handler that takes care of
+ * serving connector resources that are not served by any single connector
+ * because e.g. because they are served with strong caching or because of
+ * legacy reasons.
+ *
+ * @param createOnDemand
+ * <code>true</code> if a resource handler should be initialized
+ * if there is no handler associated with this application.
+ * </code>false</code> if </code>null</code> should be returned
+ * if there is no registered handler.
+ * @return this application's global resource handler, or <code>null</code>
+ * if there is no handler and the createOnDemand parameter is
+ * <code>false</code>.
+ *
+ * @since 7.0.0
+ */
+ public GlobalResourceHandler getGlobalResourceHandler(boolean createOnDemand) {
+ if (globalResourceHandler == null && createOnDemand) {
+ globalResourceHandler = new GlobalResourceHandler();
+ addRequestHandler(globalResourceHandler);
+ }
+
+ return globalResourceHandler;
+ }
+
+ public Collection<UIProvider> getUIProviders() {
+ return Collections.unmodifiableCollection(uiProviders);
+ }
+
+}
diff --git a/server/src/com/vaadin/server/WrappedHttpServletRequest.java b/server/src/com/vaadin/server/WrappedHttpServletRequest.java
index b069235843..4221551601 100644
--- a/server/src/com/vaadin/server/WrappedHttpServletRequest.java
+++ b/server/src/com/vaadin/server/WrappedHttpServletRequest.java
@@ -19,7 +19,6 @@ package com.vaadin.server;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
-import com.vaadin.Application;
/**
* Wrapper for {@link HttpServletRequest}.
@@ -56,18 +55,8 @@ public class WrappedHttpServletRequest extends HttpServletRequestWrapper
}
@Override
- public int getSessionMaxInactiveInterval() {
- return getSession().getMaxInactiveInterval();
- }
-
- @Override
- public Object getSessionAttribute(String name) {
- return getSession().getAttribute(name);
- }
-
- @Override
- public void setSessionAttribute(String name, Object attribute) {
- getSession().setAttribute(name, attribute);
+ public WrappedSession getWrappedSession() {
+ return new WrappedHttpSession(getSession());
}
/**
@@ -99,9 +88,7 @@ public class WrappedHttpServletRequest extends HttpServletRequestWrapper
@Override
public WebBrowser getWebBrowser() {
- ApplicationContext context = Application.getCurrent()
- .getContext();
- return context.getBrowser();
+ return VaadinSession.getCurrent().getBrowser();
}
};
}
diff --git a/server/src/com/vaadin/server/WrappedHttpSession.java b/server/src/com/vaadin/server/WrappedHttpSession.java
new file mode 100644
index 0000000000..1465588e08
--- /dev/null
+++ b/server/src/com/vaadin/server/WrappedHttpSession.java
@@ -0,0 +1,66 @@
+/*
+ * 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.http.HttpSession;
+
+/**
+ * Wrapper for {@link HttpSession}.
+ *
+ * @author Vaadin Ltd
+ * @version @VERSION@
+ * @since 7.0.0
+ */
+public class WrappedHttpSession implements WrappedSession {
+
+ private final HttpSession session;
+
+ /**
+ * Creates a new wrapped http session.
+ *
+ * @param session
+ * the http session to wrap.
+ */
+ public WrappedHttpSession(HttpSession session) {
+ this.session = session;
+ }
+
+ @Override
+ public int getMaxInactiveInterval() {
+ return session.getMaxInactiveInterval();
+ }
+
+ @Override
+ public Object getAttribute(String name) {
+ return session.getAttribute(name);
+ }
+
+ @Override
+ public void setAttribute(String name, Object value) {
+ session.setAttribute(name, value);
+ }
+
+ /**
+ * Gets the wrapped {@link HttpSession}.
+ *
+ * @return the wrapped http session
+ */
+ public HttpSession getHttpSession() {
+ return session;
+ }
+
+}
diff --git a/server/src/com/vaadin/server/WrappedPortletRequest.java b/server/src/com/vaadin/server/WrappedPortletRequest.java
index 47a8e2c358..65099add76 100644
--- a/server/src/com/vaadin/server/WrappedPortletRequest.java
+++ b/server/src/com/vaadin/server/WrappedPortletRequest.java
@@ -25,7 +25,6 @@ import javax.portlet.ClientDataRequest;
import javax.portlet.PortletRequest;
import javax.portlet.ResourceRequest;
-import com.vaadin.Application;
import com.vaadin.shared.ApplicationConstants;
/**
@@ -113,18 +112,8 @@ public class WrappedPortletRequest implements WrappedRequest {
}
@Override
- public int getSessionMaxInactiveInterval() {
- return request.getPortletSession().getMaxInactiveInterval();
- }
-
- @Override
- public Object getSessionAttribute(String name) {
- return request.getPortletSession().getAttribute(name);
- }
-
- @Override
- public void setSessionAttribute(String name, Object attribute) {
- request.getPortletSession().setAttribute(name, attribute);
+ public WrappedSession getWrappedSession() {
+ return new WrappedPortletSession(request.getPortletSession());
}
/**
@@ -161,8 +150,8 @@ public class WrappedPortletRequest implements WrappedRequest {
@Override
public WebBrowser getWebBrowser() {
- PortletApplicationContext2 context = (PortletApplicationContext2) Application
- .getCurrent().getContext();
+ VaadinPortletSession context = (VaadinPortletSession) VaadinSession
+ .getCurrent();
return context.getBrowser();
}
};
diff --git a/server/src/com/vaadin/server/WrappedPortletResponse.java b/server/src/com/vaadin/server/WrappedPortletResponse.java
index f84e3619d2..e3010501b6 100644
--- a/server/src/com/vaadin/server/WrappedPortletResponse.java
+++ b/server/src/com/vaadin/server/WrappedPortletResponse.java
@@ -29,6 +29,8 @@ import javax.portlet.MimeResponse;
import javax.portlet.PortletResponse;
import javax.portlet.ResourceResponse;
+import com.vaadin.server.VaadinPortlet.PortletDeploymentConfiguration;
+
/**
* Wrapper for {@link PortletResponse} and its subclasses.
*
@@ -46,7 +48,7 @@ public class WrappedPortletResponse implements WrappedResponse {
}
private final PortletResponse response;
- private DeploymentConfiguration deploymentConfiguration;
+ private PortletDeploymentConfiguration deploymentConfiguration;
/**
* Wraps a portlet response and an associated deployment configuration
@@ -57,7 +59,7 @@ public class WrappedPortletResponse implements WrappedResponse {
* the associated deployment configuration
*/
public WrappedPortletResponse(PortletResponse response,
- DeploymentConfiguration deploymentConfiguration) {
+ PortletDeploymentConfiguration deploymentConfiguration) {
this.response = response;
this.deploymentConfiguration = deploymentConfiguration;
}
@@ -114,7 +116,7 @@ public class WrappedPortletResponse implements WrappedResponse {
}
@Override
- public DeploymentConfiguration getDeploymentConfiguration() {
+ public PortletDeploymentConfiguration getDeploymentConfiguration() {
return deploymentConfiguration;
}
} \ No newline at end of file
diff --git a/server/src/com/vaadin/server/WrappedPortletSession.java b/server/src/com/vaadin/server/WrappedPortletSession.java
new file mode 100644
index 0000000000..eb07eb38f6
--- /dev/null
+++ b/server/src/com/vaadin/server/WrappedPortletSession.java
@@ -0,0 +1,65 @@
+/*
+ * 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.PortletSession;
+
+/**
+ * Wrapper for
+ *
+ * @author Vaadin Ltd
+ * @version @VERSION@
+ * @since 7.0.0
+ */
+public class WrappedPortletSession implements WrappedSession {
+
+ private final PortletSession session;
+
+ /**
+ * Creates a new wrapped portlet session.
+ *
+ * @param session
+ * the portlet session to wrap.
+ */
+ public WrappedPortletSession(PortletSession session) {
+ this.session = session;
+ }
+
+ @Override
+ public int getMaxInactiveInterval() {
+ return session.getMaxInactiveInterval();
+ }
+
+ @Override
+ public Object getAttribute(String name) {
+ return session.getAttribute(name);
+ }
+
+ @Override
+ public void setAttribute(String name, Object value) {
+ session.setAttribute(name, value);
+ }
+
+ /**
+ * Gets the wrapped {@link PortletSession}.
+ *
+ * @return the wrapped portlet session
+ */
+ public PortletSession getPortletSession() {
+ return session;
+ }
+}
diff --git a/server/src/com/vaadin/server/WrappedRequest.java b/server/src/com/vaadin/server/WrappedRequest.java
index 0714f73cad..5d7ece9ef1 100644
--- a/server/src/com/vaadin/server/WrappedRequest.java
+++ b/server/src/com/vaadin/server/WrappedRequest.java
@@ -32,7 +32,9 @@ import com.vaadin.ui.UI;
* A generic request to the server, wrapping a more specific request type, e.g.
* HttpServletReqest or PortletRequest.
*
- * @since 7.0
+ * @author Vaadin Ltd
+ * @version @VERSION@
+ * @since 7.0.0
*/
public interface WrappedRequest extends Serializable {
@@ -158,42 +160,15 @@ public interface WrappedRequest extends Serializable {
public String getRequestPathInfo();
/**
- * Returns the maximum time interval, in seconds, that the session
- * associated with this request will be kept open between client accesses.
+ * Gets the session associated with this request.
*
- * @return an integer specifying the number of seconds the session
- * associated with this request remains open between client requests
+ * @see WrappedSession
+ * @see HttpServletRequest#getSession()
+ * @see PortletRequest#getPortletSession()
*
- * @see javax.servlet.http.HttpSession#getMaxInactiveInterval()
- * @see javax.portlet.PortletSession#getMaxInactiveInterval()
+ * @return the wrapped session for this request
*/
- public int getSessionMaxInactiveInterval();
-
- /**
- * Gets an attribute from the session associated with this request.
- *
- * @param name
- * the name of the attribute
- * @return the attribute value, or <code>null</code> if the attribute is not
- * defined in the session
- *
- * @see javax.servlet.http.HttpSession#getAttribute(String)
- * @see javax.portlet.PortletSession#getAttribute(String)
- */
- public Object getSessionAttribute(String name);
-
- /**
- * Saves an attribute value in the session associated with this request.
- *
- * @param name
- * the name of the attribute
- * @param attribute
- * the attribute value
- *
- * @see javax.servlet.http.HttpSession#setAttribute(String, Object)
- * @see javax.portlet.PortletSession#setAttribute(String, Object)
- */
- public void setSessionAttribute(String name, Object attribute);
+ public WrappedSession getWrappedSession();
/**
* Returns the MIME type of the body of the request, or null if the type is
diff --git a/server/src/com/vaadin/server/WrappedSession.java b/server/src/com/vaadin/server/WrappedSession.java
new file mode 100644
index 0000000000..3973c257c8
--- /dev/null
+++ b/server/src/com/vaadin/server/WrappedSession.java
@@ -0,0 +1,69 @@
+/*
+ * 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.PortletSession;
+import javax.servlet.http.HttpSession;
+
+/**
+ * A generic session, wrapping a more specific session implementation, e.g.
+ * {@link HttpSession} or {@link PortletSession}.
+ *
+ *
+ * @author Vaadin Ltd
+ * @version @VERSION@
+ * @since 7.0.0
+ */
+public interface WrappedSession {
+ /**
+ * Returns the maximum time interval, in seconds, that this session will be
+ * kept open between client accesses.
+ *
+ * @return an integer specifying the number of seconds this session remains
+ * open between client requests
+ *
+ * @see javax.servlet.http.HttpSession#getMaxInactiveInterval()
+ * @see javax.portlet.PortletSession#getMaxInactiveInterval()
+ */
+ public int getMaxInactiveInterval();
+
+ /**
+ * Gets an attribute from this session.
+ *
+ * @param name
+ * the name of the attribute
+ * @return the attribute value, or <code>null</code> if the attribute is not
+ * defined in the session
+ *
+ * @see javax.servlet.http.HttpSession#getAttribute(String)
+ * @see javax.portlet.PortletSession#getAttribute(String)
+ */
+ public Object getAttribute(String name);
+
+ /**
+ * Saves an attribute value in this session.
+ *
+ * @param name
+ * the name of the attribute
+ * @param value
+ * the attribute value
+ *
+ * @see javax.servlet.http.HttpSession#setAttribute(String, Object)
+ * @see javax.portlet.PortletSession#setAttribute(String, Object)
+ */
+ public void setAttribute(String name, Object value);
+}
diff --git a/server/src/com/vaadin/ui/AbstractComponent.java b/server/src/com/vaadin/ui/AbstractComponent.java
index 37ca9f1a03..85938c4fe3 100644
--- a/server/src/com/vaadin/ui/AbstractComponent.java
+++ b/server/src/com/vaadin/ui/AbstractComponent.java
@@ -27,7 +27,6 @@ import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import com.vaadin.Application;
import com.vaadin.event.ActionManager;
import com.vaadin.event.EventRouter;
import com.vaadin.event.MethodEventSource;
@@ -38,6 +37,7 @@ import com.vaadin.server.ComponentSizeValidator;
import com.vaadin.server.ErrorMessage;
import com.vaadin.server.Resource;
import com.vaadin.server.Terminal;
+import com.vaadin.server.VaadinSession;
import com.vaadin.shared.ComponentConstants;
import com.vaadin.shared.ComponentState;
import com.vaadin.shared.ui.ComponentStateUtil;
@@ -259,7 +259,7 @@ public abstract class AbstractComponent extends AbstractClientConnector
if (parent != null) {
return parent.getLocale();
}
- final Application app = getApplication();
+ final VaadinSession app = getSession();
if (app != null) {
return app.getLocale();
}
@@ -616,7 +616,7 @@ public abstract class AbstractComponent extends AbstractClientConnector
*/
protected void focus() {
if (this instanceof Focusable) {
- final Application app = getApplication();
+ final VaadinSession app = getSession();
if (app != null) {
getUI().setFocusedComponent((Focusable) this);
delayedFocus = false;
@@ -627,31 +627,6 @@ public abstract class AbstractComponent extends AbstractClientConnector
}
/**
- * Gets the application object to which the component is attached.
- *
- * <p>
- * The method will return {@code null} if the component is not currently
- * attached to an application. This is often a problem in constructors of
- * regular components and in the initializers of custom composite
- * components. A standard workaround is to move the problematic
- * initialization to {@link #attach()}, as described in the documentation of
- * the method.
- * </p>
- * <p>
- * <b>This method is not meant to be overridden. Due to CDI requirements we
- * cannot declare it as final even though it should be final.</b>
- * </p>
- *
- * @return the parent application of the component or <code>null</code>.
- * @see #attach()
- */
- @Override
- public Application getApplication() {
- // Just make method inherited from Component interface public
- return super.getApplication();
- }
-
- /**
* Build CSS compatible string representation of height.
*
* @return CSS height
diff --git a/server/src/com/vaadin/ui/AbstractField.java b/server/src/com/vaadin/ui/AbstractField.java
index 548cb06c8f..f673babc26 100644
--- a/server/src/com/vaadin/ui/AbstractField.java
+++ b/server/src/com/vaadin/ui/AbstractField.java
@@ -697,7 +697,7 @@ public abstract class AbstractField<T> extends AbstractComponent implements
*/
public void setConverter(Class<?> datamodelType) {
Converter<T, ?> c = (Converter<T, ?>) ConverterUtil.getConverter(
- getType(), datamodelType, getApplication());
+ getType(), datamodelType, getSession());
setConverter(c);
}
diff --git a/server/src/com/vaadin/ui/Component.java b/server/src/com/vaadin/ui/Component.java
index 5bd1d53b86..492e0c25c6 100644
--- a/server/src/com/vaadin/ui/Component.java
+++ b/server/src/com/vaadin/ui/Component.java
@@ -21,7 +21,6 @@ import java.util.EventListener;
import java.util.EventObject;
import java.util.Locale;
-import com.vaadin.Application;
import com.vaadin.event.FieldEvents;
import com.vaadin.server.ClientConnector;
import com.vaadin.server.ErrorMessage;
@@ -522,34 +521,12 @@ public interface Component extends ClientConnector, Sizeable, Serializable {
public UI getUI();
/**
- * Gets the application object to which the component is attached.
- *
- * <p>
- * The method will return {@code null} if the component is not currently
- * attached to an application.
- * </p>
- *
- * <p>
- * Getting a null value is often a problem in constructors of regular
- * components and in the initializers of custom composite components. A
- * standard workaround is to use {@link Application#getCurrent()} to
- * retrieve the application instance that the current request relates to.
- * Another way is to move the problematic initialization to
- * {@link #attach()}, as described in the documentation of the method.
- * </p>
- *
- * @return the parent application of the component or <code>null</code>.
- * @see #attach()
- */
- public Application getApplication();
-
- /**
* {@inheritDoc}
*
* <p>
* Reimplementing the {@code attach()} method is useful for tasks that need
* to get a reference to the parent, window, or application object with the
- * {@link #getParent()}, {@link #getUI()}, and {@link #getApplication()}
+ * {@link #getParent()}, {@link #getUI()}, and {@link #getSession()}
* methods. A component does not yet know these objects in the constructor,
* so in such case, the methods will return {@code null}. For example, the
* following is invalid:
diff --git a/server/src/com/vaadin/ui/ConnectorTracker.java b/server/src/com/vaadin/ui/ConnectorTracker.java
index c84b75ca51..d454df98ee 100644
--- a/server/src/com/vaadin/ui/ConnectorTracker.java
+++ b/server/src/com/vaadin/ui/ConnectorTracker.java
@@ -152,7 +152,7 @@ public class ConnectorTracker implements Serializable {
}
private void removeFromGlobalResourceHandler(ClientConnector connector) {
- GlobalResourceHandler globalResourceHandler = uI.getApplication()
+ GlobalResourceHandler globalResourceHandler = uI.getSession()
.getGlobalResourceHandler(false);
// Nothing to do if there is no handler
if (globalResourceHandler != null) {
diff --git a/server/src/com/vaadin/ui/Label.java b/server/src/com/vaadin/ui/Label.java
index ff4a5dcb07..53b618a87f 100644
--- a/server/src/com/vaadin/ui/Label.java
+++ b/server/src/com/vaadin/ui/Label.java
@@ -254,7 +254,7 @@ public class Label extends AbstractComponent implements Property<String>,
newDataSource.getType())) {
// Try to find a converter
Converter<String, ?> c = ConverterUtil.getConverter(String.class,
- newDataSource.getType(), getApplication());
+ newDataSource.getType(), getSession());
setConverter(c);
}
dataSource = newDataSource;
diff --git a/server/src/com/vaadin/ui/LoginForm.java b/server/src/com/vaadin/ui/LoginForm.java
index 18927077d8..f597908b8c 100644
--- a/server/src/com/vaadin/ui/LoginForm.java
+++ b/server/src/com/vaadin/ui/LoginForm.java
@@ -24,10 +24,10 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
-import com.vaadin.Application;
import com.vaadin.server.ConnectorResource;
import com.vaadin.server.DownloadStream;
import com.vaadin.server.RequestHandler;
+import com.vaadin.server.VaadinSession;
import com.vaadin.server.WrappedRequest;
import com.vaadin.server.WrappedResponse;
import com.vaadin.shared.ApplicationConstants;
@@ -83,7 +83,7 @@ public class LoginForm extends CustomComponent {
private final RequestHandler requestHandler = new RequestHandler() {
@Override
- public boolean handleRequest(Application application,
+ public boolean handleRequest(VaadinSession application,
WrappedRequest request, WrappedResponse response)
throws IOException {
String requestPathInfo = request.getRequestPathInfo();
@@ -132,7 +132,7 @@ public class LoginForm extends CustomComponent {
* @return byte array containing login page html
*/
protected byte[] getLoginHTML() {
- String appUri = getApplication().getURL().toString();
+ String appUri = getSession().getURL().toString();
try {
return ("<!DOCTYPE html PUBLIC \"-//W3C//DTD "
@@ -186,13 +186,13 @@ public class LoginForm extends CustomComponent {
@Override
public void attach() {
super.attach();
- getApplication().addRequestHandler(requestHandler);
+ getSession().addRequestHandler(requestHandler);
iframe.setSource(loginPage);
}
@Override
public void detach() {
- getApplication().removeRequestHandler(requestHandler);
+ getSession().removeRequestHandler(requestHandler);
super.detach();
}
diff --git a/server/src/com/vaadin/ui/Table.java b/server/src/com/vaadin/ui/Table.java
index 65189fed0c..e0469f6522 100644
--- a/server/src/com/vaadin/ui/Table.java
+++ b/server/src/com/vaadin/ui/Table.java
@@ -3717,7 +3717,7 @@ public class Table extends AbstractSelect implements Action.Container,
converter = getConverter(colId);
} else {
ConverterUtil.getConverter(String.class, property.getType(),
- getApplication());
+ getSession());
}
Object value = property.getValue();
if (converter != null) {
diff --git a/server/src/com/vaadin/ui/UI.java b/server/src/com/vaadin/ui/UI.java
index ee4cb9fd2c..1c1fcf5492 100644
--- a/server/src/com/vaadin/ui/UI.java
+++ b/server/src/com/vaadin/ui/UI.java
@@ -27,7 +27,6 @@ import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Map;
-import com.vaadin.Application;
import com.vaadin.event.Action;
import com.vaadin.event.Action.Handler;
import com.vaadin.event.ActionManager;
@@ -41,6 +40,7 @@ import com.vaadin.server.PaintException;
import com.vaadin.server.PaintTarget;
import com.vaadin.server.Resource;
import com.vaadin.server.VaadinServlet;
+import com.vaadin.server.VaadinSession;
import com.vaadin.server.WrappedRequest;
import com.vaadin.server.WrappedRequest.BrowserDetails;
import com.vaadin.shared.EventId;
@@ -49,6 +49,7 @@ import com.vaadin.shared.ui.BorderStyle;
import com.vaadin.shared.ui.ui.UIConstants;
import com.vaadin.shared.ui.ui.UIServerRpc;
import com.vaadin.shared.ui.ui.UIState;
+import com.vaadin.util.CurrentInstance;
import com.vaadin.util.ReflectTools;
/**
@@ -64,9 +65,9 @@ import com.vaadin.util.ReflectTools;
* <p>
* When a new UI instance is needed, typically because the user opens a URL in a
* browser window which points to {@link VaadinServlet},
- * {@link Application#getUIForRequest(WrappedRequest)} is invoked to get a UI.
+ * {@link VaadinSession#getUIForRequest(WrappedRequest)} is invoked to get a UI.
* That method does by default create a UI according to the
- * {@value Application#UI_PARAMETER} parameter from web.xml.
+ * {@value VaadinSession#UI_PARAMETER} parameter from web.xml.
* </p>
* <p>
* After a UI has been created by the application, it is initialized using
@@ -78,7 +79,7 @@ import com.vaadin.util.ReflectTools;
* </p>
*
* @see #init(WrappedRequest)
- * @see Application#createUI(WrappedRequest)
+ * @see VaadinSession#createUI(WrappedRequest)
*
* @since 7.0
*/
@@ -88,7 +89,7 @@ public abstract class UI extends AbstractComponentContainer implements
/**
* Helper class to emulate the main window from Vaadin 6 using UIs. This
* class should be used in the same way as Window used as a browser level
- * window in Vaadin 6 with {@link com.vaadin.Application.LegacyApplication}
+ * window in Vaadin 6 with {@link com.vaadin.Application}
*/
@Deprecated
public static class LegacyWindow extends UI {
@@ -133,7 +134,7 @@ public abstract class UI extends AbstractComponentContainer implements
* The name also determines the URL that can be used for direct access
* to a window. All windows can be accessed through
* {@code http://host:port/app/win} where {@code http://host:port/app}
- * is the application URL (as returned by {@link Application#getURL()}
+ * is the application URL (as returned by {@link VaadinSession#getURL()}
* and {@code win} is the window name.
* </p>
* <p>
@@ -153,7 +154,7 @@ public abstract class UI extends AbstractComponentContainer implements
* The name also determines the URL that can be used for direct access
* to a window. All windows can be accessed through
* {@code http://host:port/app/win} where {@code http://host:port/app}
- * is the application URL (as returned by {@link Application#getURL()}
+ * is the application URL (as returned by {@link VaadinSession#getURL()}
* and {@code win} is the window name.
* </p>
* <p>
@@ -172,7 +173,7 @@ public abstract class UI extends AbstractComponentContainer implements
public void setName(String name) {
this.name = name;
// The name can not be changed in application
- if (getApplication() != null) {
+ if (getSession() != null) {
throw new IllegalStateException(
"Window name can not be changed while "
+ "the window is in application");
@@ -191,7 +192,7 @@ public abstract class UI extends AbstractComponentContainer implements
* to an application
*/
public URL getURL() {
- Application application = getApplication();
+ VaadinSession application = getSession();
if (application == null) {
return null;
}
@@ -422,7 +423,7 @@ public abstract class UI extends AbstractComponentContainer implements
/**
* The application to which this UI belongs
*/
- private Application application;
+ private VaadinSession session;
/**
* List of windows in this UI.
@@ -440,7 +441,7 @@ public abstract class UI extends AbstractComponentContainer implements
* which a request originates. A negative value indicates that the UI id has
* not yet been assigned by the Application.
*
- * @see Application#nextUIId
+ * @see VaadinSession#nextUIId
*/
private int uiId = -1;
@@ -450,11 +451,6 @@ public abstract class UI extends AbstractComponentContainer implements
*/
protected ActionManager actionManager;
- /**
- * Thread local for keeping track of the current UI.
- */
- private static final ThreadLocal<UI> currentUI = new ThreadLocal<UI>();
-
/** Identifies the click event */
private ConnectorTracker connectorTracker = new ConnectorTracker(this);
@@ -566,9 +562,29 @@ public abstract class UI extends AbstractComponentContainer implements
throw new UnsupportedOperationException();
}
+ /**
+ * Gets the application object to which the component is attached.
+ *
+ * <p>
+ * The method will return {@code null} if the component is not currently
+ * attached to an application.
+ * </p>
+ *
+ * <p>
+ * Getting a null value is often a problem in constructors of regular
+ * components and in the initializers of custom composite components. A
+ * standard workaround is to use {@link VaadinSession#getCurrent()} to
+ * retrieve the application instance that the current request relates to.
+ * Another way is to move the problematic initialization to
+ * {@link #attach()}, as described in the documentation of the method.
+ * </p>
+ *
+ * @return the parent application of the component or <code>null</code>.
+ * @see #attach()
+ */
@Override
- public Application getApplication() {
- return application;
+ public VaadinSession getSession() {
+ return session;
}
@Override
@@ -679,25 +695,25 @@ public abstract class UI extends AbstractComponentContainer implements
* This method is mainly intended for internal use by the framework.
* </p>
*
- * @param application
+ * @param session
* the application to set
*
* @throws IllegalStateException
* if the application has already been set
*
- * @see #getApplication()
+ * @see #getSession()
*/
- public void setApplication(Application application) {
- if ((application == null) == (this.application == null)) {
+ public void setSession(VaadinSession session) {
+ if ((session == null) == (this.session == null)) {
throw new IllegalStateException("Application has already been set");
} else {
- if (application == null) {
+ if (session == null) {
detach();
}
- this.application = application;
+ this.session = session;
}
- if (application != null) {
+ if (session != null) {
attach();
}
}
@@ -706,8 +722,8 @@ public abstract class UI extends AbstractComponentContainer implements
* Gets the id of the UI, used to identify this UI within its application
* when processing requests. The UI id should be present in every request to
* the server that originates from this UI.
- * {@link Application#getUIForRequest(WrappedRequest)} uses this id to find
- * the route to which the request belongs.
+ * {@link VaadinSession#getUIForRequest(WrappedRequest)} uses this id to
+ * find the route to which the request belongs.
*
* @return
*/
@@ -719,7 +735,7 @@ public abstract class UI extends AbstractComponentContainer implements
* Adds a window as a subwindow inside this UI. To open a new browser window
* or tab, you should instead use {@link open(Resource)} with an url
* pointing to this application and ensure
- * {@link Application#createUI(WrappedRequest)} returns an appropriate UI
+ * {@link VaadinSession#createUI(WrappedRequest)} returns an appropriate UI
* for the request.
*
* @param window
@@ -735,7 +751,7 @@ public abstract class UI extends AbstractComponentContainer implements
throw new NullPointerException("Argument must not be null");
}
- if (window.getApplication() != null) {
+ if (window.getUI() != null && window.getUI().getSession() != null) {
throw new IllegalArgumentException(
"Window is already attached to an application.");
}
@@ -940,7 +956,8 @@ public abstract class UI extends AbstractComponentContainer implements
throw new IllegalStateException("UI id has already been defined");
}
this.uiId = uiId;
- theme = getApplication().getThemeForUI(request, getClass());
+ theme = getSession().getUiProvider(request, getClass())
+ .getThemeForUI(request, getClass());
getPage().init(request);
@@ -981,7 +998,7 @@ public abstract class UI extends AbstractComponentContainer implements
* @see ThreadLocal
*/
public static void setCurrent(UI ui) {
- currentUI.set(ui);
+ CurrentInstance.setInheritable(UI.class, ui);
}
/**
@@ -994,7 +1011,7 @@ public abstract class UI extends AbstractComponentContainer implements
* @see #setCurrent(UI)
*/
public static UI getCurrent() {
- return currentUI.get();
+ return CurrentInstance.get(UI.class);
}
public void setScrollTop(int scrollTop) {
@@ -1296,7 +1313,7 @@ public abstract class UI extends AbstractComponentContainer implements
* heartbeat for this UI.
*
* @see #heartbeat()
- * @see Application#closeInactiveUIs()
+ * @see VaadinSession#closeInactiveUIs()
*
* @return The time the last heartbeat request occurred.
*/
diff --git a/server/src/com/vaadin/util/CurrentInstance.java b/server/src/com/vaadin/util/CurrentInstance.java
new file mode 100644
index 0000000000..8478ba9486
--- /dev/null
+++ b/server/src/com/vaadin/util/CurrentInstance.java
@@ -0,0 +1,131 @@
+/*
+ * 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.util;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+
+/**
+ * Keeps track of various thread local instances used by the framework.
+ *
+ * @author Vaadin Ltd
+ * @version @VERSION@
+ * @since 7.0.0
+ */
+public class CurrentInstance {
+ private final Object instance;
+ private final boolean inheritable;
+
+ private static InheritableThreadLocal<Map<Class<?>, CurrentInstance>> instances = new InheritableThreadLocal<Map<Class<?>, CurrentInstance>>() {
+ @Override
+ protected Map<Class<?>, CurrentInstance> childValue(
+ Map<Class<?>, CurrentInstance> parentValue) {
+ Map<Class<?>, CurrentInstance> value = new HashMap<Class<?>, CurrentInstance>();
+
+ // Copy all inheritable values to child map
+ for (Entry<Class<?>, CurrentInstance> e : parentValue.entrySet()) {
+ if (e.getValue().inheritable) {
+ value.put(e.getKey(), e.getValue());
+ }
+ }
+
+ return value;
+ }
+
+ @Override
+ protected Map<java.lang.Class<?>, CurrentInstance> initialValue() {
+ return new HashMap<Class<?>, CurrentInstance>();
+ }
+ };
+
+ private CurrentInstance(Object instance, boolean inheritable) {
+ this.instance = instance;
+ this.inheritable = inheritable;
+ }
+
+ /**
+ * Gets the current instance of a specific type if available.
+ *
+ * @param type
+ * the class to get an instance of
+ * @return the current instance or the provided type, or <code>null</code>
+ * if there is no current instance.
+ */
+ public static <T> T get(Class<T> type) {
+ CurrentInstance currentInstance = instances.get().get(type);
+ if (currentInstance != null) {
+ return type.cast(currentInstance.instance);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Sets the current instance of the given type.
+ *
+ * @see #setInheritable(Class, Object)
+ * @see ThreadLocal
+ *
+ * @param type
+ * the class that should be used when getting the current
+ * instance back
+ * @param instance
+ * the actual instance
+ */
+ public static <T> void set(Class<T> type, T instance) {
+ set(type, instance, false);
+ }
+
+ /**
+ * Sets the current inheritable instance of the given type. A current
+ * instance that is inheritable will be available for child threads.
+ *
+ * @see #set(Class, Object)
+ * @see InheritableThreadLocal
+ *
+ * @param type
+ * the class that should be used when getting the current
+ * instance back
+ * @param instance
+ * the actual instance
+ */
+ public static <T> void setInheritable(Class<T> type, T instance) {
+ set(type, instance, true);
+ }
+
+ private static <T> void set(Class<T> type, T instance, boolean inheritable) {
+ if (instance == null) {
+ instances.get().remove(type);
+ } else {
+ assert type.isInstance(instance) : "Invald instance type";
+ CurrentInstance previousInstance = instances.get().put(type,
+ new CurrentInstance(instance, inheritable));
+ if (previousInstance != null) {
+ assert previousInstance.inheritable == inheritable : "Inheritable status mismatch for "
+ + type;
+ }
+ }
+ }
+
+ /**
+ * Clears all current instances.
+ */
+ public static void clearAll() {
+ instances.get().clear();
+ }
+}
diff --git a/server/tests/src/com/vaadin/server/TestAbstractApplicationServletStaticFilesLocation.java b/server/tests/src/com/vaadin/server/TestAbstractApplicationServletStaticFilesLocation.java
index b936cae1a5..2aa8d04364 100644
--- a/server/tests/src/com/vaadin/server/TestAbstractApplicationServletStaticFilesLocation.java
+++ b/server/tests/src/com/vaadin/server/TestAbstractApplicationServletStaticFilesLocation.java
@@ -13,6 +13,7 @@ import javax.servlet.http.HttpServletRequest;
import junit.framework.TestCase;
+import com.vaadin.DefaultApplicationConfiguration;
import com.vaadin.server.VaadinServlet.ServletDeploymentConfiguration;
public class TestAbstractApplicationServletStaticFilesLocation extends TestCase {
@@ -32,7 +33,8 @@ public class TestAbstractApplicationServletStaticFilesLocation extends TestCase
.getDeclaredField("deploymentConfiguration");
f.setAccessible(true);
f.set(servlet, new ServletDeploymentConfiguration(servlet,
- new Properties()));
+ new DefaultApplicationConfiguration(servlet.getClass(),
+ new Properties())));
}
diff --git a/server/tests/src/com/vaadin/tests/VaadinClasses.java b/server/tests/src/com/vaadin/tests/VaadinClasses.java
index 15e1283e47..b30ddcee7e 100644
--- a/server/tests/src/com/vaadin/tests/VaadinClasses.java
+++ b/server/tests/src/com/vaadin/tests/VaadinClasses.java
@@ -15,7 +15,7 @@ import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
-import com.vaadin.Application;
+import com.vaadin.server.VaadinSession;
import com.vaadin.ui.Component;
import com.vaadin.ui.ComponentContainer;
import com.vaadin.ui.CustomComponent;
@@ -144,7 +144,7 @@ public class VaadinClasses {
String basePackage, String[] ignoredPackages) throws IOException {
List<Class<? extends T>> classes = new ArrayList<Class<? extends T>>();
String basePackageDirName = "/" + basePackage.replace('.', '/');
- URL location = Application.class.getResource(basePackageDirName);
+ URL location = VaadinSession.class.getResource(basePackageDirName);
if (location.getProtocol().equals("file")) {
try {
File f = new File(location.toURI());
diff --git a/server/tests/src/com/vaadin/tests/data/converter/ConverterFactory.java b/server/tests/src/com/vaadin/tests/data/converter/ConverterFactory.java
index 6393d61981..b64514ea14 100644
--- a/server/tests/src/com/vaadin/tests/data/converter/ConverterFactory.java
+++ b/server/tests/src/com/vaadin/tests/data/converter/ConverterFactory.java
@@ -19,9 +19,9 @@ import java.util.Locale;
import junit.framework.TestCase;
-import com.vaadin.Application;
import com.vaadin.data.util.converter.Converter;
import com.vaadin.data.util.converter.DefaultConverterFactory;
+import com.vaadin.server.VaadinSession;
import com.vaadin.ui.TextField;
public class ConverterFactory extends TestCase {
@@ -65,14 +65,14 @@ public class ConverterFactory extends TestCase {
}
public void testApplicationConverterFactoryInBackgroundThread() {
- Application.setCurrent(null);
- final Application appWithCustomIntegerConverter = new Application();
+ VaadinSession.setCurrent(null);
+ final VaadinSession appWithCustomIntegerConverter = new VaadinSession();
appWithCustomIntegerConverter
.setConverterFactory(new ConverterFactory42());
TextField tf = new TextField("", "123") {
@Override
- public Application getApplication() {
+ public VaadinSession getSession() {
return appWithCustomIntegerConverter;
};
};
@@ -83,10 +83,10 @@ public class ConverterFactory extends TestCase {
}
public void testApplicationConverterFactoryForDetachedComponent() {
- final Application appWithCustomIntegerConverter = new Application();
+ final VaadinSession appWithCustomIntegerConverter = new VaadinSession();
appWithCustomIntegerConverter
.setConverterFactory(new ConverterFactory42());
- Application.setCurrent(appWithCustomIntegerConverter);
+ VaadinSession.setCurrent(appWithCustomIntegerConverter);
TextField tf = new TextField("", "123");
tf.setConverter(Integer.class);
@@ -96,14 +96,14 @@ public class ConverterFactory extends TestCase {
}
public void testApplicationConverterFactoryForDifferentThanCurrentApplication() {
- final Application fieldAppWithCustomIntegerConverter = new Application();
+ final VaadinSession fieldAppWithCustomIntegerConverter = new VaadinSession();
fieldAppWithCustomIntegerConverter
.setConverterFactory(new ConverterFactory42());
- Application.setCurrent(new Application());
+ VaadinSession.setCurrent(new VaadinSession());
TextField tf = new TextField("", "123") {
@Override
- public Application getApplication() {
+ public VaadinSession getSession() {
return fieldAppWithCustomIntegerConverter;
}
};
diff --git a/server/tests/src/com/vaadin/tests/server/TestMimeTypes.java b/server/tests/src/com/vaadin/tests/server/TestMimeTypes.java
index dc730f6cc4..12e5b09632 100644
--- a/server/tests/src/com/vaadin/tests/server/TestMimeTypes.java
+++ b/server/tests/src/com/vaadin/tests/server/TestMimeTypes.java
@@ -2,21 +2,12 @@ package com.vaadin.tests.server;
import junit.framework.TestCase;
-import com.vaadin.Application;
import com.vaadin.server.ClassResource;
import com.vaadin.ui.Embedded;
public class TestMimeTypes extends TestCase {
public void testEmbeddedPDF() {
- Application app = new Application() {
-
- @Override
- public void init() {
- // TODO Auto-generated method stub
-
- }
- };
Embedded e = new Embedded("A pdf", new ClassResource("file.pddf"));
assertEquals("Invalid mimetype", "application/octet-stream",
e.getMimeType());
diff --git a/server/tests/src/com/vaadin/tests/server/TestStreamVariableMapping.java b/server/tests/src/com/vaadin/tests/server/TestStreamVariableMapping.java
index f3b367483a..0dd7efa507 100644
--- a/server/tests/src/com/vaadin/tests/server/TestStreamVariableMapping.java
+++ b/server/tests/src/com/vaadin/tests/server/TestStreamVariableMapping.java
@@ -4,9 +4,9 @@ import junit.framework.TestCase;
import org.easymock.EasyMock;
-import com.vaadin.Application;
import com.vaadin.server.CommunicationManager;
import com.vaadin.server.StreamVariable;
+import com.vaadin.server.VaadinSession;
import com.vaadin.server.WrappedRequest;
import com.vaadin.ui.UI;
import com.vaadin.ui.Upload;
@@ -21,7 +21,7 @@ public class TestStreamVariableMapping extends TestCase {
@Override
protected void setUp() throws Exception {
- final Application application = new Application();
+ final VaadinSession application = new VaadinSession();
final UI uI = new UI() {
@Override
protected void init(WrappedRequest request) {
@@ -30,7 +30,7 @@ public class TestStreamVariableMapping extends TestCase {
}
@Override
- public Application getApplication() {
+ public VaadinSession getSession() {
return application;
}
};
@@ -66,12 +66,7 @@ public class TestStreamVariableMapping extends TestCase {
}
private CommunicationManager createCommunicationManager() {
- return new CommunicationManager(new Application() {
- @Override
- public void init() {
- // TODO Auto-generated method stub
- }
- });
+ return new CommunicationManager(new VaadinSession());
}
}
diff --git a/server/tests/src/com/vaadin/tests/server/TransactionListenersConcurrency.java b/server/tests/src/com/vaadin/tests/server/TransactionListenersConcurrency.java
deleted file mode 100644
index 05ffcd1e36..0000000000
--- a/server/tests/src/com/vaadin/tests/server/TransactionListenersConcurrency.java
+++ /dev/null
@@ -1,201 +0,0 @@
-package com.vaadin.tests.server;
-
-import static org.easymock.EasyMock.createMock;
-
-import java.lang.Thread.UncaughtExceptionHandler;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Properties;
-import java.util.Random;
-
-import javax.servlet.http.HttpSession;
-
-import junit.framework.TestCase;
-
-import org.easymock.EasyMock;
-
-import com.vaadin.Application;
-import com.vaadin.Application.ApplicationStartEvent;
-import com.vaadin.server.ApplicationContext;
-import com.vaadin.server.DeploymentConfiguration;
-import com.vaadin.server.ServletApplicationContext;
-
-public class TransactionListenersConcurrency extends TestCase {
-
- /**
- * This test starts N threads concurrently. Each thread creates an
- * application which adds a transaction listener to the context. A
- * transaction is then started for each application. Some semi-random delays
- * are included so that calls to addTransactionListener and
- * WebApplicationContext.startTransaction are mixed.
- *
- */
- public void testTransactionListeners() throws Exception {
- final List<Throwable> exceptions = new ArrayList<Throwable>();
-
- HttpSession session = createSession();
- final ServletApplicationContext context = ServletApplicationContext
- .getApplicationContext(session);
- List<Thread> threads = new ArrayList<Thread>();
-
- for (int i = 0; i < 5; i++) {
- Thread t = new Thread(new Runnable() {
-
- @Override
- public void run() {
- Application app = new Application() {
-
- @Override
- public void init() {
- // Sleep 0-1000ms so another transaction has time to
- // start before we add the transaction listener.
- try {
- Thread.sleep((long) (1000 * new Random()
- .nextDouble()));
- } catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
-
- getContext().addTransactionListener(
- new DelayTransactionListener(2000));
- }
-
- };
-
- // Start the application so the transaction listener is
- // called later on.
- try {
- DeploymentConfiguration dc = EasyMock
- .createMock(DeploymentConfiguration.class);
- EasyMock.expect(dc.isProductionMode()).andReturn(true);
- EasyMock.expect(dc.getInitParameters()).andReturn(
- new Properties());
- EasyMock.replay(dc);
-
- app.start(new ApplicationStartEvent(new URL(
- "http://localhost/"), dc, context));
- } catch (MalformedURLException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
-
- try {
- // Call the transaction listener using reflection as
- // startTransaction is protected.
-
- Method m = ApplicationContext.class.getDeclaredMethod(
- "startTransaction", Application.class,
- Object.class);
- m.setAccessible(true);
- m.invoke(context, app, null);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-
- });
-
- threads.add(t);
- t.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
-
- @Override
- public void uncaughtException(Thread t, Throwable e) {
- if (e.getCause() != null) {
- e = e.getCause();
- }
- exceptions.add(e);
- }
- });
- }
-
- // Start the threads and wait for all of them to finish
- for (Thread t : threads) {
- t.start();
- }
- int running = threads.size();
-
- while (running > 0) {
- for (Iterator<Thread> i = threads.iterator(); i.hasNext();) {
- Thread t = i.next();
- if (!t.isAlive()) {
- running--;
- i.remove();
- }
- }
- }
-
- for (Throwable t : exceptions) {
- if (t instanceof InvocationTargetException) {
- t = t.getCause();
- }
- if (t != null) {
- t.printStackTrace(System.err);
- fail(t.getClass().getName());
- }
- }
-
- System.out.println("Done, all ok");
-
- }
-
- /**
- * Creates a HttpSession mock
- *
- */
- private static HttpSession createSession() {
- HttpSession session = createMock(HttpSession.class);
- EasyMock.expect(
- session.getAttribute(ServletApplicationContext.class.getName()))
- .andReturn(null).anyTimes();
- session.setAttribute(
- EasyMock.eq(ServletApplicationContext.class.getName()),
- EasyMock.anyObject());
-
- EasyMock.replay(session);
- return session;
- }
-
- /**
- * A transaction listener that just sleeps for the given amount of time in
- * transactionStart and transactionEnd.
- *
- */
- public static class DelayTransactionListener implements
- ApplicationContext.TransactionListener {
-
- private int delay;
-
- public DelayTransactionListener(int delay) {
- this.delay = delay;
- }
-
- @Override
- public void transactionStart(Application application,
- Object transactionData) {
- try {
- Thread.sleep(delay);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
-
- }
-
- @Override
- public void transactionEnd(Application application,
- Object transactionData) {
- try {
- Thread.sleep(delay);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
-
- }
- }
-
-}
diff --git a/server/tests/src/com/vaadin/tests/server/component/abstractfield/AbstractFieldValueConversions.java b/server/tests/src/com/vaadin/tests/server/component/abstractfield/AbstractFieldValueConversions.java
index 57af748247..b48ad62bcc 100644
--- a/server/tests/src/com/vaadin/tests/server/component/abstractfield/AbstractFieldValueConversions.java
+++ b/server/tests/src/com/vaadin/tests/server/component/abstractfield/AbstractFieldValueConversions.java
@@ -4,10 +4,10 @@ import java.util.Locale;
import junit.framework.TestCase;
-import com.vaadin.Application;
import com.vaadin.data.util.MethodProperty;
import com.vaadin.data.util.converter.Converter;
import com.vaadin.data.util.converter.StringToIntegerConverter;
+import com.vaadin.server.VaadinSession;
import com.vaadin.tests.data.bean.Address;
import com.vaadin.tests.data.bean.Country;
import com.vaadin.tests.data.bean.Person;
@@ -186,11 +186,11 @@ public class AbstractFieldValueConversions extends TestCase {
}
public void testNumberDoubleConverterChange() {
- final Application a = new Application();
- Application.setCurrent(a);
+ final VaadinSession a = new VaadinSession();
+ VaadinSession.setCurrent(a);
TextField tf = new TextField() {
@Override
- public Application getApplication() {
+ public VaadinSession getSession() {
return a;
}
};
diff --git a/server/tests/src/com/vaadin/tests/server/component/abstractfield/DefaultConverterFactory.java b/server/tests/src/com/vaadin/tests/server/component/abstractfield/DefaultConverterFactory.java
index 25430fc9a5..a1b6541ee0 100644
--- a/server/tests/src/com/vaadin/tests/server/component/abstractfield/DefaultConverterFactory.java
+++ b/server/tests/src/com/vaadin/tests/server/component/abstractfield/DefaultConverterFactory.java
@@ -5,8 +5,8 @@ import java.util.Locale;
import junit.framework.TestCase;
-import com.vaadin.Application;
import com.vaadin.data.util.MethodProperty;
+import com.vaadin.server.VaadinSession;
import com.vaadin.tests.data.bean.Address;
import com.vaadin.tests.data.bean.Country;
import com.vaadin.tests.data.bean.Person;
@@ -26,8 +26,8 @@ public class DefaultConverterFactory extends TestCase {
}
public void testDefaultNumberConversion() {
- Application app = new Application();
- Application.setCurrent(app);
+ VaadinSession app = new VaadinSession();
+ VaadinSession.setCurrent(app);
TextField tf = new TextField();
tf.setLocale(new Locale("en", "US"));
tf.setPropertyDataSource(new MethodProperty<Integer>(paulaBean,
diff --git a/server/tests/src/com/vaadin/tests/server/component/abstractfield/RemoveListenersOnDetach.java b/server/tests/src/com/vaadin/tests/server/component/abstractfield/RemoveListenersOnDetach.java
index 18567b62f0..c9f579a887 100644
--- a/server/tests/src/com/vaadin/tests/server/component/abstractfield/RemoveListenersOnDetach.java
+++ b/server/tests/src/com/vaadin/tests/server/component/abstractfield/RemoveListenersOnDetach.java
@@ -4,10 +4,10 @@ import static org.junit.Assert.assertEquals;
import org.junit.Test;
-import com.vaadin.Application;
import com.vaadin.data.Property;
import com.vaadin.data.util.AbstractProperty;
import com.vaadin.data.util.converter.Converter.ConversionException;
+import com.vaadin.server.VaadinSession;
import com.vaadin.server.WrappedRequest;
import com.vaadin.ui.AbstractField;
import com.vaadin.ui.UI;
@@ -18,7 +18,7 @@ public class RemoveListenersOnDetach {
int numReadOnlyChanges = 0;
AbstractField field = new AbstractField() {
- final private Application application = new Application() {
+ final private VaadinSession application = new VaadinSession() {
};
private UI uI = new UI() {
@@ -29,7 +29,7 @@ public class RemoveListenersOnDetach {
}
@Override
- public Application getApplication() {
+ public VaadinSession getSession() {
return application;
}
@@ -59,7 +59,7 @@ public class RemoveListenersOnDetach {
};
@Override
- public Application getApplication() {
+ public VaadinSession getSession() {
return application;
};
};
diff --git a/server/tests/src/com/vaadin/tests/server/component/label/LabelConverters.java b/server/tests/src/com/vaadin/tests/server/component/label/LabelConverters.java
index 48279c7c88..22cd450af7 100644
--- a/server/tests/src/com/vaadin/tests/server/component/label/LabelConverters.java
+++ b/server/tests/src/com/vaadin/tests/server/component/label/LabelConverters.java
@@ -17,9 +17,9 @@ package com.vaadin.tests.server.component.label;
import junit.framework.TestCase;
-import com.vaadin.Application;
import com.vaadin.data.Property;
import com.vaadin.data.util.MethodProperty;
+import com.vaadin.server.VaadinSession;
import com.vaadin.tests.data.bean.Person;
import com.vaadin.ui.Label;
@@ -37,7 +37,7 @@ public class LabelConverters extends TestCase {
}
public void testIntegerDataSource() {
- Application.setCurrent(new Application());
+ VaadinSession.setCurrent(new VaadinSession());
Label l = new Label("Foo");
Property ds = new MethodProperty<Integer>(Person.createTestPerson1(),
"age");
diff --git a/server/tests/src/com/vaadin/tests/server/component/root/CustomUIClassLoader.java b/server/tests/src/com/vaadin/tests/server/component/root/CustomUIClassLoader.java
index 89da55a31f..acc2ed3b14 100644
--- a/server/tests/src/com/vaadin/tests/server/component/root/CustomUIClassLoader.java
+++ b/server/tests/src/com/vaadin/tests/server/component/root/CustomUIClassLoader.java
@@ -8,11 +8,13 @@ import junit.framework.TestCase;
import org.easymock.EasyMock;
-import com.vaadin.Application;
-import com.vaadin.Application.ApplicationStartEvent;
+import com.vaadin.DefaultApplicationConfiguration;
+import com.vaadin.server.ApplicationConfiguration;
import com.vaadin.server.DefaultUIProvider;
import com.vaadin.server.DeploymentConfiguration;
+import com.vaadin.server.VaadinSession;
import com.vaadin.server.WrappedRequest;
+import com.vaadin.server.VaadinSession.ApplicationStartEvent;
import com.vaadin.ui.UI;
public class CustomUIClassLoader extends TestCase {
@@ -51,7 +53,7 @@ public class CustomUIClassLoader extends TestCase {
* if thrown
*/
public void testWithNullClassLoader() throws Exception {
- Application application = createStubApplication();
+ VaadinSession application = createStubApplication();
application.start(new ApplicationStartEvent(null,
createConfigurationMock(), null));
@@ -62,15 +64,11 @@ public class CustomUIClassLoader extends TestCase {
assertEquals(MyUI.class, uiClass);
}
- private static DeploymentConfiguration createConfigurationMock() {
- DeploymentConfiguration configurationMock = EasyMock
- .createMock(DeploymentConfiguration.class);
- EasyMock.expect(configurationMock.isProductionMode()).andReturn(false);
- EasyMock.expect(configurationMock.getInitParameters()).andReturn(
- new Properties());
-
- EasyMock.replay(configurationMock);
- return configurationMock;
+ private static ApplicationConfiguration createConfigurationMock() {
+ Properties properties = new Properties();
+ properties.put(VaadinSession.UI_PARAMETER, MyUI.class.getName());
+ return new DefaultApplicationConfiguration(CustomUIClassLoader.class,
+ properties);
}
private static WrappedRequest createRequestMock(ClassLoader classloader) {
@@ -99,7 +97,7 @@ public class CustomUIClassLoader extends TestCase {
public void testWithClassLoader() throws Exception {
LoggingClassLoader loggingClassLoader = new LoggingClassLoader();
- Application application = createStubApplication();
+ VaadinSession application = createStubApplication();
application.start(new ApplicationStartEvent(null,
createConfigurationMock(), null));
@@ -114,15 +112,11 @@ public class CustomUIClassLoader extends TestCase {
}
- private Application createStubApplication() {
- return new Application() {
+ private VaadinSession createStubApplication() {
+ return new VaadinSession() {
@Override
- public String getProperty(String name) {
- if (name.equals(UI_PARAMETER)) {
- return MyUI.class.getName();
- } else {
- return super.getProperty(name);
- }
+ public ApplicationConfiguration getConfiguration() {
+ return createConfigurationMock();
}
};
}
diff --git a/server/tests/src/com/vaadin/tests/server/component/window/AddRemoveSubWindow.java b/server/tests/src/com/vaadin/tests/server/component/window/AddRemoveSubWindow.java
index 88bc28bbc8..2e59f9ee41 100644
--- a/server/tests/src/com/vaadin/tests/server/component/window/AddRemoveSubWindow.java
+++ b/server/tests/src/com/vaadin/tests/server/component/window/AddRemoveSubWindow.java
@@ -13,7 +13,7 @@ import com.vaadin.ui.Window;
public class AddRemoveSubWindow {
- public class TestApp extends Application.LegacyApplication {
+ public class TestApp extends Application {
@Override
public void init() {
diff --git a/server/tests/src/com/vaadin/tests/server/component/window/AttachDetachWindow.java b/server/tests/src/com/vaadin/tests/server/component/window/AttachDetachWindow.java
index 0fb0765c9f..ec722fdffb 100644
--- a/server/tests/src/com/vaadin/tests/server/component/window/AttachDetachWindow.java
+++ b/server/tests/src/com/vaadin/tests/server/component/window/AttachDetachWindow.java
@@ -5,7 +5,8 @@ import static org.junit.Assert.assertTrue;
import org.junit.Test;
-import com.vaadin.Application;
+import com.vaadin.server.ClientConnector;
+import com.vaadin.server.VaadinSession;
import com.vaadin.server.WrappedRequest;
import com.vaadin.ui.Label;
import com.vaadin.ui.UI;
@@ -14,7 +15,7 @@ import com.vaadin.ui.Window;
public class AttachDetachWindow {
- private Application testApp = new Application();
+ private VaadinSession testApp = new VaadinSession();
private interface TestContainer {
public boolean attachCalled();
@@ -23,7 +24,7 @@ public class AttachDetachWindow {
public TestContent getTestContent();
- public Application getApplication();
+ public VaadinSession getSession();
}
private class TestWindow extends Window implements TestContainer {
@@ -61,6 +62,11 @@ public class AttachDetachWindow {
public TestContent getTestContent() {
return testContent;
}
+
+ @Override
+ public VaadinSession getSession() {
+ return super.getSession();
+ }
}
private class TestContent extends VerticalLayout {
@@ -155,7 +161,7 @@ public class AttachDetachWindow {
assertUnattached(sub);
// attaching main should recurse to sub
- main.setApplication(testApp);
+ main.setSession(testApp);
assertAttached(main);
assertAttached(sub);
}
@@ -165,7 +171,7 @@ public class AttachDetachWindow {
assertUnattached(main);
assertUnattached(sub);
- main.setApplication(testApp);
+ main.setSession(testApp);
assertAttached(main);
assertUnattached(sub);
@@ -177,7 +183,7 @@ public class AttachDetachWindow {
@Test
public void removeSubWindowBeforeDetachingMainWindow() {
- main.setApplication(testApp);
+ main.setSession(testApp);
main.addWindow(sub);
// sub should be detached when removing from attached main
@@ -186,18 +192,18 @@ public class AttachDetachWindow {
assertDetached(sub);
// main detach should recurse to sub
- main.setApplication(null);
+ main.setSession(null);
assertDetached(main);
assertDetached(sub);
}
@Test
public void removeSubWindowAfterDetachingMainWindow() {
- main.setApplication(testApp);
+ main.setSession(testApp);
main.addWindow(sub);
// main detach should recurse to sub
- main.setApplication(null);
+ main.setSession(null);
assertDetached(main);
assertDetached(sub);
@@ -219,22 +225,31 @@ public class AttachDetachWindow {
assertTrue("window child attach not called",
testContent.childAttachCalled);
- assertSame("window not attached", win.getApplication(), testApp);
- assertSame("window content not attached", testContent.getApplication(),
- testApp);
- assertSame("window children not attached",
- testContent.child.getApplication(), testApp);
+ assertSame("window not attached", win.getSession(), testApp);
+ assertSame("window content not attached", testContent.getUI()
+ .getSession(), testApp);
+ assertSame("window children not attached", testContent.child.getUI()
+ .getSession(), testApp);
}
/**
* Asserts that win and its children are not attached.
*/
private void assertUnattached(TestContainer win) {
- assertSame("window not detached", win.getApplication(), null);
- assertSame("window content not detached", win.getTestContent()
- .getApplication(), null);
+ assertSame("window not detached", win.getSession(), null);
+ assertSame("window content not detached",
+ getVaadinSession(win.getTestContent()), null);
assertSame("window children not detached",
- win.getTestContent().child.getApplication(), null);
+ getVaadinSession(win.getTestContent().child), null);
+ }
+
+ private VaadinSession getVaadinSession(ClientConnector testContainer) {
+ UI ui = testContainer.getUI();
+ if (ui != null) {
+ return ui.getSession();
+ } else {
+ return null;
+ }
}
/**