import java.util.Enumeration;
import java.util.EventListener;
import java.util.EventObject;
+import java.util.HashMap;
+import java.util.HashSet;
import java.util.Hashtable;
-import java.util.Iterator;
import java.util.LinkedList;
import java.util.Locale;
+import java.util.Map;
+import java.util.Map.Entry;
import java.util.Properties;
+import java.util.Set;
+import java.util.WeakHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import com.vaadin.annotations.RootInitRequiresBrowserDetals;
+import com.vaadin.annotations.RootTheme;
+import com.vaadin.annotations.RootWidgetset;
+ import com.vaadin.data.util.converter.Converter;
+ import com.vaadin.data.util.converter.ConverterFactory;
+ import com.vaadin.data.util.converter.DefaultConverterFactory;
import com.vaadin.service.ApplicationContext;
import com.vaadin.terminal.ApplicationResource;
-import com.vaadin.terminal.DownloadStream;
+import com.vaadin.terminal.CombinedRequest;
import com.vaadin.terminal.ErrorMessage;
-import com.vaadin.terminal.ParameterHandler;
+import com.vaadin.terminal.RequestHandler;
import com.vaadin.terminal.SystemError;
import com.vaadin.terminal.Terminal;
-import com.vaadin.terminal.URIHandler;
import com.vaadin.terminal.VariableOwner;
+import com.vaadin.terminal.WrappedRequest;
+import com.vaadin.terminal.WrappedRequest.BrowserDetails;
+import com.vaadin.terminal.WrappedResponse;
+import com.vaadin.terminal.gwt.client.ApplicationConnection;
+import com.vaadin.terminal.gwt.server.AbstractApplicationServlet;
import com.vaadin.terminal.gwt.server.ChangeVariablesErrorEvent;
-import com.vaadin.terminal.gwt.server.PortletApplicationContext;
import com.vaadin.terminal.gwt.server.WebApplicationContext;
import com.vaadin.ui.AbstractComponent;
+ import com.vaadin.ui.AbstractField;
+import com.vaadin.ui.Root;
import com.vaadin.ui.Window;
/**
*/
private Terminal.ErrorListener errorHandler = this;
- /**
- * <p>
- * Gets a window by name. Returns <code>null</code> if the application is
- * not running or it does not contain a window corresponding to the name.
- * </p>
- *
- * <p>
- * All windows can be referenced by their names in url
- * <code>http://host:port/foo/bar/</code> where
- * <code>http://host:port/foo/</code> is the application url as returned by
- * getURL() and <code>bar</code> is the name of the window.
- * </p>
- *
- * <p>
- * One should note that this method can, as a side effect create new windows
- * if needed by the application. This can be achieved by overriding the
- * default implementation.
- * </p>
- *
- * <p>
- * If for some reason user opens another window with same url that is
- * already open, name is modified by adding "_12345678" postfix to the name,
- * where 12345678 is a random number. One can decide to create another
- * window-object for those windows (recommended) or to discard the postfix.
- * If the user has two browser windows pointing to the same window-object on
- * server, synchronization errors are likely to occur.
- * </p>
- *
- * <p>
- * If no browser-level windowing is used, all defaults are fine and this
- * method can be left as is. In case browser-level windows are needed, it is
- * recommended to create new window-objects on this method from their names
- * if the super.getWindow() does not find existing windows. See below for
- * implementation example: <code><pre>
- // If we already have the requested window, use it
- Window w = super.getWindow(name);
- if (w == null) {
- // If no window found, create it
- w = new Window(name);
- // set windows name to the one requested
- w.setName(name);
- // add it to this application
- addWindow(w);
- // ensure use of window specific url
- w.open(new ExternalResource(w.getURL().toString()));
- // add some content
- w.addComponent(new Label("Test window"));
- }
- return w;</pre></code>
- * </p>
- *
- * <p>
- * <strong>Note</strong> that all returned Window objects must be added to
- * this application instance.
- *
- * <p>
- * The method should return null if the window does not exists (and is not
- * created as a side-effect) or if the application is not running anymore.
- * </p>
- *
- * @param name
- * the name of the window.
- * @return the window associated with the given URI or <code>null</code>
- */
- public Window getWindow(String name) {
-
- // For closed app, do not give any windows
- if (!isRunning()) {
- return null;
- }
+ /**
+ * The converter factory that is used for all fields in the application.
+ */
+ // private ConverterFactory converterFactory = new
+ // DefaultConverterFactory();
+ private static ConverterFactory converterFactory = new DefaultConverterFactory();
+
+ private LinkedList<RequestHandler> requestHandlers = new LinkedList<RequestHandler>();
- // Gets the window by name
- final Window window = windows.get(name);
+ private int nextRootId = 0;
+ private Map<Integer, Root> roots = new HashMap<Integer, Root>();
- return window;
- }
+ private boolean productionMode = true;
/**
- * Adds a new window to the application.
- *
- * <p>
- * This implicitly invokes the
- * {@link com.vaadin.ui.Window#setApplication(Application)} method.
- * </p>
- *
- * <p>
- * Note that all application-level windows can be accessed by their names in
- * url <code>http://host:port/foo/bar/</code> where
- * <code>http://host:port/foo/</code> is the application url as returned by
- * getURL() and <code>bar</code> is the name of the window. Also note that
- * not all windows should be added to application - one can also add windows
- * inside other windows - these windows show as smaller windows inside those
- * windows.
- * </p>
- *
- * @param window
- * the new <code>Window</code> to add. If the name of the window
- * is <code>null</code>, an unique name is automatically given
- * for the window.
- * @throws IllegalArgumentException
- * if a window with the same name as the new window already
- * exists in the application.
- * @throws NullPointerException
- * if the given <code>Window</code> is <code>null</code>.
- */
- public void addWindow(Window window) throws IllegalArgumentException,
- NullPointerException {
-
- // Nulls can not be added to application
- if (window == null) {
- return;
- }
-
- // Check that one is not adding a sub-window to application
- if (window.getParent() != null) {
- throw new IllegalArgumentException(
- "Window was already added inside another window"
- + " - it can not be added to application also.");
- }
-
- // Gets the naming proposal from window
- String name = window.getName();
-
- // Checks that the application does not already contain
- // window having the same name
- if (name != null && windows.containsKey(name)) {
-
- // If the window is already added
- if (window == windows.get(name)) {
- return;
- }
-
- // Otherwise complain
- throw new IllegalArgumentException("Window with name '"
- + window.getName()
- + "' is already present in the application");
- }
-
- // If the name of the window is null, the window is automatically named
- if (name == null) {
- boolean accepted = false;
- while (!accepted) {
-
- // Try another name
- synchronized (this) {
- name = String.valueOf(nextWindowId);
- nextWindowId++;
- }
-
- if (!windows.containsKey(name)) {
- accepted = true;
- }
- }
- window.setName(name);
- }
-
- // Adds the window to application
- windows.put(name, window);
- window.setApplication(this);
-
- fireWindowAttachEvent(window);
-
- // If no main window is set, declare the window to be main window
- if (getMainWindow() == null) {
- mainWindow = window;
- }
- }
+ * Keeps track of requests for which a root should be created once more
+ * information is available.
+ */
+ private Map<Integer, PendingRootRequest> pendingRoots = new HashMap<Integer, PendingRootRequest>();
/**
- * Send information to all listeners about new Windows associated with this
- * application.
- *
- * @param window
+ * Keeps track of the roots that should be remembered when the browser is
+ * refreshed.
*/
- private void fireWindowAttachEvent(Window window) {
- // Fires the window attach event
- if (windowAttachListeners != null) {
- final Object[] listeners = windowAttachListeners.toArray();
- final WindowAttachEvent event = new WindowAttachEvent(window);
- for (int i = 0; i < listeners.length; i++) {
- ((WindowAttachListener) listeners[i]).windowAttached(event);
- }
- }
- }
+ private Map<String, Integer> retainOnRefreshRoots = new WeakHashMap<String, Integer>();
/**
- * Removes the specified window from the application.
- *
- * <p>
- * Removing the main window of the Application also sets the main window to
- * null. One must another window to be the main window after this with
- * {@link #setMainWindow(Window)}.
- * </p>
- *
+ * Keeps track of which roots have been inited.
* <p>
- * Note that removing window from the application does not close the browser
- * window - the window is only removed from the server-side.
+ * TODO Investigate whether this might be derived from the different states
+ * in getRootForRrequest.
* </p>
- *
- * @param window
- * the window to be removed.
*/
- public void removeWindow(Window window) {
- if (window != null && windows.contains(window)) {
-
- // Removes the window from application
- windows.remove(window.getName());
-
- // If the window was main window, clear it
- if (getMainWindow() == window) {
- setMainWindow(null);
- }
-
- // Removes the application from window
- if (window.getApplication() == this) {
- window.setApplication(null);
- }
-
- fireWindowDetachEvent(window);
- }
- }
-
- private void fireWindowDetachEvent(Window window) {
- // Fires the window detach event
- if (windowDetachListeners != null) {
- final Object[] listeners = windowDetachListeners.toArray();
- final WindowDetachEvent event = new WindowDetachEvent(window);
- for (int i = 0; i < listeners.length; i++) {
- ((WindowDetachListener) listeners[i]).windowDetached(event);
- }
- }
- }
+ private Set<Integer> initedRoots = new HashSet<Integer>();
/**
* Gets the user of the application.