*/
public static final String ROOT_PARAMETER = "root";
+ /**
+ * Represents a strategy for retaining root instances when the contents of
+ * the browser have been reloaded, e.g. if the user presses refresh or
+ * navigates back to the application from another page.
+ *
+ * @since 7.0
+ */
+ public interface RootPreserveStrategy extends Serializable {
+ /**
+ * Finds the id of an existing root that should be used to serve a
+ * request.
+ *
+ * @param request
+ * the request to get the root for
+ * @return integer id of the root, or <code>null</code> if no root is
+ * found
+ * @throws RootRequiresMoreInformation
+ * if full details from the browser are required to resolve
+ * the root
+ */
+ public Integer getPreservedRootForRequest(WrappedRequest request)
+ throws RootRequiresMoreInformation;
+
+ /**
+ * Used to tell whether the browser details are required when
+ * {@link #registerRoot(Root, WrappedRequest)} is called.
+ *
+ * @return <code>true</code> if the browser details are needed,
+ * <code>false</code> if they are not needed
+ */
+ public boolean reqsterRequiresBrowserDetails();
+
+ /**
+ * This method is called by the framework when a root has been
+ * initialized and should possibly be preserved for future lookups.
+ *
+ * @param root
+ * the newly initialized root
+ * @param request
+ * the associated request
+ */
+ public void registerRoot(Root root, WrappedRequest request);
+ }
+
+ public static class WindowNameRootPreserveStrategy implements
+ RootPreserveStrategy {
+ /**
+ * Keeps track of the roots that should be remembered when the browser
+ * is refreshed.
+ */
+ private final Map<String, Integer> retainOnRefreshRoots = new HashMap<String, Integer>();
+
+ public Integer getPreservedRootForRequest(WrappedRequest request)
+ throws RootRequiresMoreInformation {
+ if (retainOnRefreshRoots.isEmpty()) {
+ return null;
+ }
+ BrowserDetails browserDetails = request.getBrowserDetails();
+ if (browserDetails == null) {
+ throw new RootRequiresMoreInformation();
+ } else {
+ String windowName = browserDetails.getWindowName();
+ return retainOnRefreshRoots.get(windowName);
+ }
+ }
+
+ public void registerRoot(Root root, WrappedRequest request) {
+ String windowName = request.getBrowserDetails().getWindowName();
+ Integer rootId = Integer.valueOf(root.getRootId());
+ retainOnRefreshRoots.put(windowName, rootId);
+ }
+
+ public boolean reqsterRequiresBrowserDetails() {
+ return true;
+ }
+ }
+
/**
* A special application designed to help migrating applications from Vaadin
* 6 to Vaadin 7. The legacy application supports setting a main window,
*/
private Map<Integer, PendingRootRequest> pendingRoots = new HashMap<Integer, PendingRootRequest>();
- /**
- * Keeps track of the roots that should be remembered when the browser is
- * refreshed.
- */
- private Map<String, Integer> retainOnRefreshRoots = new HashMap<String, Integer>();
+ private RootPreserveStrategy rootPreserveStrategy = null;
/**
* Keeps track of which roots have been inited.
Integer rootId = getRootId(request);
synchronized (this) {
- boolean preserveRootState = preserveRootStateOnRefresh();
+ RootPreserveStrategy rootPreserveStrategy = getRootPreserveStrategy();
BrowserDetails browserDetails = request.getBrowserDetails();
if (browserDetails != null) {
// Don't wait for a second request any more
pendingRoots.remove(rootId);
-
- if (preserveRootState) {
- // Check for a known window.name
- Integer retainedRootId = retainOnRefreshRoots
- .get(browserDetails.getWindowName());
- if (retainedRootId != null) {
- rootId = retainedRootId;
- }
- }
}
root = roots.get(rootId);
- if (root == null) {
- if (preserveRootState && browserDetails == null
- && !retainOnRefreshRoots.isEmpty()) {
- // If there might already be an existing root, request
- // information to potentially find it
- throw new RootRequiresMoreInformation();
+ if (root == null && rootPreserveStrategy != null) {
+ // Check for a known root
+ Integer retainedRootId = rootPreserveStrategy
+ .getPreservedRootForRequest(request);
+ if (retainedRootId != null) {
+ rootId = retainedRootId;
+ root = roots.get(rootId);
}
+ }
+ if (root == null) {
// Throws exception if root can not yet be created
root = getRoot(request);
}
if (!initedRoots.contains(rootId)) {
- boolean initRequiresBrowserDetails = preserveRootState
+ boolean initRequiresBrowserDetails = (rootPreserveStrategy != null && rootPreserveStrategy
+ .reqsterRequiresBrowserDetails())
|| root.getClass().isAnnotationPresent(
RootInitRequiresBrowserDetals.class);
if (initRequiresBrowserDetails && browserDetails == null) {
pendingRoots.put(rootId, new PendingRootRequest(request));
} else {
- if (preserveRootState) {
- // Remember the window name of this root
- retainOnRefreshRoots.put(
- browserDetails.getWindowName(), rootId);
+ if (rootPreserveStrategy != null) {
+ // Remember this root
+ rootPreserveStrategy.registerRoot(root, request);
}
root.doInit(request);
return root;
}
- protected boolean preserveRootStateOnRefresh() {
- return false;
- }
-
/**
* Internal helper to finds the root id for a request.
*
return rootId;
}
+ /**
+ * Gets the current strategy for preserving Root instances e.g. when the
+ * browser window is reloaded.
+ *
+ * @return the current root preserver strategy, or <code>null</code> if
+ * roots should not be preserved
+ *
+ * @see RootPreserveStrategy
+ */
+ public RootPreserveStrategy getRootPreserveStrategy() {
+ return rootPreserveStrategy;
+ }
+
+ /**
+ * Sets the current strategy for preserving Roots e.g. when the browser
+ * window is reloaded.
+ *
+ * @param rootPreserveStrategy
+ * the new root preserve strategy
+ */
+ public void setRootPreserveStrategy(
+ RootPreserveStrategy rootPreserveStrategy) {
+ this.rootPreserveStrategy = rootPreserveStrategy;
+ }
+
/**
* Checks whether there's a pending initialization for the root with the
* given id.