瀏覽代碼

Initial support for lazy root creation

tags/7.0.0.alpha1
Leif Åstrand 12 年之前
父節點
當前提交
55948aefe8

+ 67
- 23
WebContent/VAADIN/vaadinBootstrap.js 查看文件

@@ -43,8 +43,6 @@
var url = basePath + widgetset + "/" + widgetset + ".nocache.js?" + new Date().getTime();
//document.write("<script type='text/javascript' src='"+url+"'></script>");
var scriptTag = document.createElement('script');
scriptTag.setAttribute('type', 'text/javascript');
scriptTag.setAttribute('src', url);
@@ -58,7 +56,7 @@
if (defaults) {
throw "Defaults already defined";
}
log("Got defaults", defaults)
log("Got defaults", d)
defaults = d;
},
initApplication: function(appId, config) {
@@ -73,27 +71,45 @@
}
return value;
}

var themeUri = getConfig('themeUri');
if (themeUri) {
loadTheme(themeUri);
}
var widgetsetBase = getConfig('widgetsetBase');
var widgetset = getConfig('widgetset');
if (widgetset && widgetsetBase) {
loadWidgetset(widgetsetBase, widgetset);
if (widgetsetApps[widgetset]) {
widgetsetApps[widgetset].push(appId);
} else {
widgetsetApps[widgetset] = [appId];
}
}
if (getConfig("debug")) {
// TODO debug state is now global for the entire page, but should somehow only be set for the current application
window.vaadin.debug = true;
}
var fetchRootConfig = function() {
log('Fetching root config');
var url = getConfig('appUri');
// Root id
url += ((/\?/).test(url) ? "&" : "?") + "browserDetails";
url += '&rootId=' + getConfig('rootId');
// Uri fragment
url += '&f=' + encodeURIComponent(location.hash);
// Timestamp to avoid caching
url += '&' + (new Date()).getTime();
var r = new XMLHttpRequest();
r.open('POST', url, true);
r.onreadystatechange = function (aEvt) {
if (r.readyState == 4) {
if (r.status == 200){
log(r.responseText);
// TODO Does this work in all supported browsers?
var updatedConfig = JSON.parse(r.responseText);
// Copy new properties to the config object
for (var property in updatedConfig) {
if (updatedConfig.hasOwnProperty(property)) {
config[property] = updatedConfig[property];
}
}
// Try bootstrapping again, this time without fetching missing info
bootstrapApp(false);
} else {
log('Error', r.statusText);
}
}
};
r.send(null);
log('sending request to ', url);
};
//Export public data
var app = {
@@ -101,6 +117,34 @@
};
apps[appId] = app;
var bootstrapApp = function(mayDefer) {
var themeUri = getConfig('themeUri');
if (themeUri) {
loadTheme(themeUri);
}
var widgetsetBase = getConfig('widgetsetBase');
var widgetset = getConfig('widgetset');
if (widgetset && widgetsetBase) {
loadWidgetset(widgetsetBase, widgetset);
if (widgetsetApps[widgetset]) {
widgetsetApps[widgetset].push(appId);
} else {
widgetsetApps[widgetset] = [appId];
}
} else if (mayDefer) {
fetchRootConfig();
} else {
throw "Widgetset not defined";
}
}
bootstrapApp(true);

if (getConfig("debug")) {
// TODO debug state is now global for the entire page, but should somehow only be set for the current application
window.vaadin.debug = true;
}
return app;
},
getApp: function(appId) {

+ 91
- 29
src/com/vaadin/Application.java 查看文件

@@ -29,6 +29,7 @@ import java.util.regex.Pattern;

import com.vaadin.service.ApplicationContext;
import com.vaadin.terminal.ApplicationResource;
import com.vaadin.terminal.CombinedRequest;
import com.vaadin.terminal.ErrorMessage;
import com.vaadin.terminal.RequestHandler;
import com.vaadin.terminal.SystemError;
@@ -36,6 +37,7 @@ import com.vaadin.terminal.Terminal;
import com.vaadin.terminal.VariableOwner;
import com.vaadin.terminal.WrappedRequest;
import com.vaadin.terminal.WrappedResponse;
import com.vaadin.terminal.gwt.client.ApplicationConnection;
import com.vaadin.terminal.gwt.server.ChangeVariablesErrorEvent;
import com.vaadin.terminal.gwt.server.WebApplicationContext;
import com.vaadin.ui.AbstractComponent;
@@ -118,8 +120,6 @@ public class Application implements Terminal.ErrorListener, Serializable {
"mainWindow has already been set");
}
this.mainWindow = mainWindow;
registerRoot(mainWindow);
mainWindow.init(null);
}

public Root getMainWindow() {
@@ -171,8 +171,6 @@ public class Application implements Terminal.ErrorListener, Serializable {

public void addWindow(Root root, String name) {
legacyRootNames.put(name, root);
registerRoot(root);
root.init(null);
}

public void removeWindow(Root root) {
@@ -211,6 +209,24 @@ public class Application implements Terminal.ErrorListener, Serializable {
}
}

private static class PendingRootRequest {

private final Map<String, String[]> parameterMap;
private final String pathInfo;

public PendingRootRequest(WrappedRequest request) {
parameterMap = new HashMap<String, String[]>(
request.getParameterMap());
pathInfo = request.getRequestPathInfo();
}

public CombinedRequest getCombinedRequest(
final WrappedRequest secondRequest) {
return new CombinedRequest(secondRequest,
Collections.unmodifiableMap(parameterMap), pathInfo);
}
}

private final static Logger logger = Logger.getLogger(Application.class
.getName());

@@ -283,6 +299,12 @@ public class Application implements Terminal.ErrorListener, Serializable {

private boolean productionMode = true;

/**
* 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>();

/**
* Gets the user of the application.
*
@@ -1570,27 +1592,8 @@ public class Application implements Terminal.ErrorListener, Serializable {

}

public Root getRoot(WrappedRequest request) {
// TODO What if getRoot is called again for this request?

// TODO implement support for throwing exception if more
// information is required to create a root
Root root = createRoot(request);

registerRoot(root);

// TODO implement lazy init of root if indicated by annotation
root.init(request);

return root;
}

protected void registerRoot(Root root) {
root.registerRoot(this, nextRootId++);
roots.put(Integer.valueOf(root.getRootId()), root);
}

protected Root createRoot(WrappedRequest request) {
protected Root getRoot(WrappedRequest request)
throws RootRequiresMoreInformation {
String rootClassName = getRootClassName(request);
try {
Class<? extends Root> rootClass = Class.forName(rootClassName)
@@ -1666,11 +1669,70 @@ public class Application implements Terminal.ErrorListener, Serializable {
currentApplication.set(application);
}

public Root getRootById(int rootId) {
return roots.get(Integer.valueOf(rootId));
}

public boolean isProductionMode() {
return productionMode;
}

public int registerPendingRoot(WrappedRequest request) {
int rootId = nextRootId++;
pendingRoots.put(Integer.valueOf(rootId), new PendingRootRequest(
request));
return rootId;
}

public CombinedRequest getCombinedRequest(WrappedRequest request) {
PendingRootRequest pendingRootRequest = pendingRoots
.get(getRootId(request));
if (pendingRootRequest == null) {
return null;
} else {
return pendingRootRequest.getCombinedRequest(request);
}
}

public Root getRootForRequest(WrappedRequest request)
throws RootRequiresMoreInformation {
Root root = Root.getCurrentRoot();
if (root != null) {
return root;
}
Integer rootId = getRootId(request);

synchronized (this) {
PendingRootRequest pendingRootRequest = pendingRoots.remove(rootId);
if (pendingRootRequest == null && rootId != null) {
root = roots.get(rootId);
} else {
root = getRoot(request);
if (root.getApplication() == null) {
root.setApplication(this);
}
if (root.getRootId() < 0) {
int id = (rootId != null ? rootId.intValue() : nextRootId++);
root.setRootId(id);
roots.put(Integer.valueOf(root.getRootId()), root);

// TODO implement lazy init of root if indicated by
// annotation
root.init(request);
}
}
}

Root.setCurrentRoot(root);
return root;
}

private Integer getRootId(WrappedRequest request) {
if (request instanceof CombinedRequest) {
// Combined requests has the rootid parameter in the second request
CombinedRequest combinedRequest = (CombinedRequest) request;
request = combinedRequest.getSecondRequest();
}
String rootIdString = request
.getParameter(ApplicationConnection.ROOT_ID_PARAMETER);
Integer rootId = rootIdString == null ? null
: new Integer(rootIdString);
return rootId;
}
}

+ 17
- 0
src/com/vaadin/RootRequiresMoreInformation.java 查看文件

@@ -0,0 +1,17 @@
/*
@ITMillApache2LicenseForJavaFiles@
*/

package com.vaadin;

/**
* Exception that is thrown to indicate that creating or initializing the root
* requires information from the web browser (e.g. screen size or URI fragment)
* to be present.
*
* This exception may not be thrown if that information is already present in
* the current WrappedRequest.
*/
public class RootRequiresMoreInformation extends Exception {
// Nothing of interest here
}

+ 89
- 0
src/com/vaadin/terminal/CombinedRequest.java 查看文件

@@ -0,0 +1,89 @@
/*
@ITMillApache2LicenseForJavaFiles@
*/

package com.vaadin.terminal;

import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.Map;

public class CombinedRequest implements WrappedRequest {

private final WrappedRequest secondRequest;
private final Map<String, String[]> parameterMap;
private final String pathInfo;

public CombinedRequest(WrappedRequest secondRequest,
Map<String, String[]> parameterMap, String pathInfo) {
this.secondRequest = secondRequest;
this.parameterMap = parameterMap;
this.pathInfo = pathInfo;
}

public String getParameter(String parameter) {
String[] strings = parameterMap.get(parameter);
if (strings == null || strings.length == 0) {
return null;
} else {
return strings[0];
}
}

public Map<String, String[]> getParameterMap() {
return Collections.unmodifiableMap(parameterMap);
}

public int getContentLength() {
return secondRequest.getContentLength();
}

public InputStream getInputStream() throws IOException {
return secondRequest.getInputStream();
}

public Object getAttribute(String name) {
return secondRequest.getAttribute(name);
}

public void setAttribute(String name, Object value) {
secondRequest.setAttribute(name, value);
}

public String getRequestPathInfo() {
return pathInfo;
}

public int getSessionMaxInactiveInterval() {
return secondRequest.getSessionMaxInactiveInterval();
}

public Object getSessionAttribute(String name) {
return secondRequest.getSessionAttribute(name);
}

public void setSessionAttribute(String name, Object attribute) {
secondRequest.setSessionAttribute(name, attribute);
}

public String getContentType() {
return secondRequest.getContentType();
}

public String getStaticFileLocation() {
return secondRequest.getStaticFileLocation();
}

public BrowserDetails getBrowserDetails() {
return new BrowserDetails() {
public String getUriFragmet() {
return secondRequest.getParameter("f");
}
};
}

public WrappedRequest getSecondRequest() {
return secondRequest;
}
}

+ 6
- 0
src/com/vaadin/terminal/WrappedRequest.java 查看文件

@@ -10,6 +10,10 @@ import java.io.Serializable;
import java.util.Map;

public interface WrappedRequest extends Serializable {
public interface BrowserDetails {
public String getUriFragmet();
}
/**
* Get the named HTTP or portlet request parameter.
*
@@ -65,4 +69,6 @@ public interface WrappedRequest extends Serializable {

public String getStaticFileLocation();

public BrowserDetails getBrowserDetails();

}

+ 2
- 2
src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java 查看文件

@@ -447,8 +447,8 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet
// root = application.getRoot();
break;
default:
root = applicationManager.getApplicationRoot(
wrappedRequest, application);
root = application
.getRootForRequest(wrappedRequest);
}
// if window not found, not a problem - use null
}

+ 13
- 3
src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java 查看文件

@@ -452,14 +452,17 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
return;
} else if (requestType == RequestType.UIDL) {
// Handles AJAX UIDL requests
Root root = applicationManager.getApplicationRoot(
wrappedRequest, application);
Root root = application.getRootForRequest(wrappedRequest);
if (root == null) {
throw new ServletException(ERROR_NO_WINDOW_FOUND);
}
applicationManager.handleUidlRequest(wrappedRequest,
wrappedResponse, servletWrapper, root);
return;
} else if (requestType == RequestType.BROWSER_DETAILS) {
applicationManager.handleBrowserDetailsRequest(wrappedRequest,
wrappedResponse, application);
return;
}

// Removes application if it has stopped (mayby by thread or
@@ -1228,12 +1231,14 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
}

protected enum RequestType {
FILE_UPLOAD, UIDL, OTHER, STATIC_FILE, APPLICATION_RESOURCE;
FILE_UPLOAD, BROWSER_DETAILS, UIDL, OTHER, STATIC_FILE, APPLICATION_RESOURCE;
}

protected RequestType getRequestType(HttpServletRequest request) {
if (isFileUploadRequest(request)) {
return RequestType.FILE_UPLOAD;
} else if (isBrowserDetailsRequest(request)) {
return RequestType.BROWSER_DETAILS;
} else if (isUIDLRequest(request)) {
return RequestType.UIDL;
} else if (isStaticResourceRequest(request)) {
@@ -1247,6 +1252,11 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements

}

private static boolean isBrowserDetailsRequest(HttpServletRequest request) {
return "POST".equals(request.getMethod())
&& request.getParameter("browserDetails") != null;
}

private boolean isApplicationRequest(HttpServletRequest request) {
String path = getRequestPathInfo(request);
if (path != null && path.startsWith("/APP/")) {

+ 46
- 32
src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java 查看文件

@@ -43,6 +43,10 @@ import java.util.logging.Logger;

import com.vaadin.Application;
import com.vaadin.Application.SystemMessages;
import com.vaadin.RootRequiresMoreInformation;
import com.vaadin.external.json.JSONException;
import com.vaadin.external.json.JSONObject;
import com.vaadin.terminal.CombinedRequest;
import com.vaadin.terminal.PaintException;
import com.vaadin.terminal.PaintTarget;
import com.vaadin.terminal.Paintable;
@@ -90,15 +94,18 @@ public abstract class AbstractCommunicationManager implements
.getLogger(AbstractCommunicationManager.class.getName());

private static final RequestHandler APP_RESOURCE_HANDLER = new ApplicationResourceHandler();
private static final RequestHandler AJAX_PAGE_HANDLER = new AjaxPageHandler() {
private static final AjaxPageHandler AJAX_PAGE_HANDLER = new AjaxPageHandler() {

@Override
protected String getApplicationOrSystemProperty(
WrappedRequest request, String parameter,
String defaultValue) {
protected String getApplicationOrSystemProperty(WrappedRequest request,
String parameter, String defaultValue) {
if (request instanceof CombinedRequest) {
CombinedRequest combinedRequest = (CombinedRequest) request;
request = combinedRequest.getSecondRequest();
}
WrappedHttpServletRequest r = (WrappedHttpServletRequest) request;
return r.getServlet().getApplicationOrSystemProperty(
parameter, defaultValue);
return r.getServlet().getApplicationOrSystemProperty(parameter,
defaultValue);
}

};
@@ -1628,32 +1635,6 @@ public abstract class AbstractCommunicationManager implements
outWriter.print("]"); // Close locales
}

/**
* Gets the existing application or creates a new one. Get a window within
* an application based on the requested URI.
*
* @param request
* the HTTP Request.
* @param application
* the Application to query for window.
* @return Window matching the given URI or null if not found.
*/
public Root getApplicationRoot(WrappedRequest request,
Application application) {
String rootIdString = request
.getParameter(ApplicationConnection.ROOT_ID_PARAMETER);
Root root = null;
synchronized (application) {
if (rootIdString != null) {
int rootId = Integer.parseInt(rootIdString);
root = application.getRootById(rootId);
}
}

Root.setCurrentRoot(root);
return root;
}

/**
* Ends the Application.
*
@@ -1951,6 +1932,39 @@ public abstract class AbstractCommunicationManager implements
return application.handleRequest(request, response);
}

public void handleBrowserDetailsRequest(WrappedRequest request,
WrappedResponse response, Application application)
throws IOException {

// TODO Handle npe if id has not been registered
CombinedRequest combinedRequest = application
.getCombinedRequest(request);

try {
Root root = application.getRootForRequest(combinedRequest);

// Use the same logic as for determined roots
String widgetset = AJAX_PAGE_HANDLER.getWidgetsetForRoot(
combinedRequest, root);
String theme = AJAX_PAGE_HANDLER.getThemeForRoot(combinedRequest,
root);
String themeUri = AJAX_PAGE_HANDLER.getThemeUri(theme,
combinedRequest);

JSONObject params = new JSONObject();
params.put("widgetset", widgetset);
params.put("themeUri", themeUri);
response.getWriter().write(params.toString());
} catch (RootRequiresMoreInformation e) {
// Requiring more information at this point is not allowed
// TODO handle in a better way
throw new RuntimeException(e);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

/**
* Stream that extracts content from another stream until the boundary
* string is encountered.

+ 59
- 33
src/com/vaadin/terminal/gwt/server/AjaxPageHandler.java 查看文件

@@ -7,6 +7,7 @@ import java.io.OutputStreamWriter;
import javax.servlet.http.HttpServletResponse;

import com.vaadin.Application;
import com.vaadin.RootRequiresMoreInformation;
import com.vaadin.external.json.JSONException;
import com.vaadin.external.json.JSONObject;
import com.vaadin.terminal.RequestHandler;
@@ -22,15 +23,21 @@ public abstract class AjaxPageHandler implements RequestHandler {
throws IOException {

// TODO Should all urls be handled here?
Root root = application.getRoot(request);

if (root == null) {
writeError(response, new Throwable("No Root found"));
return true;
int rootId;
try {
Root root = application.getRootForRequest(request);
if (root == null) {
writeError(response, new Throwable("No Root found"));
return true;
}

rootId = root.getRootId();
} catch (RootRequiresMoreInformation e) {
rootId = application.registerPendingRoot(request);
}

try {
writeAjaxPage(request, response, root);
writeAjaxPage(request, response, application, rootId);
} catch (JSONException e) {
writeError(response, e);
}
@@ -39,13 +46,14 @@ public abstract class AjaxPageHandler implements RequestHandler {
}

protected final void writeAjaxPage(WrappedRequest request,
WrappedResponse response, Root root) throws IOException,
JSONException {
Application application = root.getApplication();
WrappedResponse response, Application application, int rootId)
throws IOException, JSONException {
final BufferedWriter page = new BufferedWriter(new OutputStreamWriter(
response.getOutputStream(), "UTF-8"));

String title = ((root.getCaption() == null) ? "Vaadin "
Root root = Root.getCurrentRoot();

String title = ((root == null || root.getCaption() == null) ? "Vaadin "
+ AbstractApplicationServlet.VERSION_MAJOR : root.getCaption());

/* Fetch relative url to application */
@@ -78,9 +86,11 @@ public abstract class AjaxPageHandler implements RequestHandler {
}
appId = appId + "-" + hashCode;

String widgetset = getWidgetsetForRoot(request, root);

// TODO include initial UIDL in the scripts?
writeAjaxPageHtmlVaadinScripts(themeName, page, appUrl, themeUri,
appId, request, root);
writeAjaxPageHtmlVaadinScripts(page, appUrl, themeUri, appId, request,
application, rootId, widgetset);

/*- Add classnames;
* .v-app
@@ -109,6 +119,23 @@ public abstract class AjaxPageHandler implements RequestHandler {
page.close();
}

public String getWidgetsetForRoot(WrappedRequest request, Root root) {
if (root == null) {
// Defer widgetset selection
return null;
}

String widgetset = root.getApplication().getWidgetsetForRoot(root);
if (widgetset == null) {
widgetset = getApplicationOrSystemProperty(request,
AbstractApplicationServlet.PARAMETER_WIDGETSET,
AbstractApplicationServlet.DEFAULT_WIDGETSET);
}

widgetset = AbstractApplicationServlet.stripSpecialChars(widgetset);
return widgetset;
}

/**
* Method to write the div element into which that actual Vaadin application
* is rendered.
@@ -178,22 +205,20 @@ public abstract class AjaxPageHandler implements RequestHandler {
* <p>
* Override this method if you want to add some custom html around scripts.
*
* @param themeName
* @param page
* @param appUrl
* @param themeUri
* @param appId
* @param request
* @param application
* @param rootId
* @throws IOException
* @throws JSONException
*/
protected void writeAjaxPageHtmlVaadinScripts(String themeName,
final BufferedWriter page, String appUrl, String themeUri,
String appId, WrappedRequest request, Root root)
throws IOException, JSONException {

Application application = root.getApplication();
protected void writeAjaxPageHtmlVaadinScripts(final BufferedWriter page,
String appUrl, String themeUri, String appId,
WrappedRequest request, Application application, int rootId,
String widgetset) throws IOException, JSONException {

String staticFileLocation = request.getStaticFileLocation();

@@ -225,8 +250,7 @@ public abstract class AjaxPageHandler implements RequestHandler {

defaults.put("appUri", appUrl);

appConfig
.put(ApplicationConnection.ROOT_ID_PARAMETER, root.getRootId());
appConfig.put(ApplicationConnection.ROOT_ID_PARAMETER, rootId);

if (isStandalone()) {
defaults.put("standalone", true);
@@ -262,12 +286,6 @@ public abstract class AjaxPageHandler implements RequestHandler {

defaults.put("widgetsetBase", widgetsetBase);

String widgetset = application.getWidgetsetForRoot(root);
widgetset = getApplicationOrSystemProperty(request,
AbstractApplicationServlet.PARAMETER_WIDGETSET,
AbstractApplicationServlet.DEFAULT_WIDGETSET);

widgetset = AbstractApplicationServlet.stripSpecialChars(widgetset);
appConfig.put("widgetset", widgetset);

page.write("vaadin.setDefaults(");
@@ -327,10 +345,12 @@ public abstract class AjaxPageHandler implements RequestHandler {
+ "html, body {height:100%;margin:0;}</style>");

// Add favicon links
page.write("<link rel=\"shortcut icon\" type=\"image/vnd.microsoft.icon\" href=\""
+ themeUri + "/favicon.ico\" />");
page.write("<link rel=\"icon\" type=\"image/vnd.microsoft.icon\" href=\""
+ themeUri + "/favicon.ico\" />");
if (themeUri != null) {
page.write("<link rel=\"shortcut icon\" type=\"image/vnd.microsoft.icon\" href=\""
+ themeUri + "/favicon.ico\" />");
page.write("<link rel=\"icon\" type=\"image/vnd.microsoft.icon\" href=\""
+ themeUri + "/favicon.ico\" />");
}

page.write("<title>"
+ AbstractApplicationServlet.safeEscapeForHtml(title)
@@ -387,7 +407,10 @@ public abstract class AjaxPageHandler implements RequestHandler {
* @param request
* @return
*/
private String getThemeUri(String themeName, WrappedRequest request) {
public String getThemeUri(String themeName, WrappedRequest request) {
if (themeName == null) {
return null;
}
final String staticFilePath = request.getStaticFileLocation();
return staticFilePath + "/"
+ AbstractApplicationServlet.THEME_DIRECTORY_PATH + themeName;
@@ -400,7 +423,10 @@ public abstract class AjaxPageHandler implements RequestHandler {
* @param root
* @return
*/
private String getThemeForRoot(WrappedRequest request, Root root) {
public String getThemeForRoot(WrappedRequest request, Root root) {
if (root == null) {
return null;
}
// Finds theme name
String themeName;


+ 5
- 0
src/com/vaadin/terminal/gwt/server/WrappedHttpServletRequest.java 查看文件

@@ -95,4 +95,9 @@ public class WrappedHttpServletRequest implements WrappedRequest {
public String getStaticFileLocation() {
return servlet.getStaticFilesLocation(request);
}

public BrowserDetails getBrowserDetails() {
// No browserDetails available for normal requests
return null;
}
}

+ 5
- 0
src/com/vaadin/terminal/gwt/server/WrappedPortletRequest.java 查看文件

@@ -108,4 +108,9 @@ public class WrappedPortletRequest implements WrappedRequest {
throw new UnsupportedOperationException("Please implement me!");
}

public BrowserDetails getBrowserDetails() {
// No browserDetails available for normal requests
return null;
}

}

+ 9
- 3
src/com/vaadin/ui/Root.java 查看文件

@@ -85,7 +85,7 @@ public class Root extends AbstractComponentContainer implements
*/
private Component scrollIntoView;

private int rootId;
private int rootId = -1;

/**
* Keeps track of the Actions added to this component, and manages the
@@ -225,17 +225,23 @@ public class Root extends AbstractComponentContainer implements
return Collections.singleton((Component) getContent()).iterator();
}

public void registerRoot(Application application, int rootId) {
public void setApplication(Application application) {
if (application == null) {
throw new NullPointerException("application");
} else if (this.application != null) {
throw new IllegalStateException("Application has already been set");
} else {
this.application = application;
this.rootId = rootId;
}
}

public void setRootId(int rootId) {
if (this.rootId != -1) {
throw new IllegalStateException("Root id has already been defined");
}
this.rootId = rootId;
}

public int getRootId() {
return rootId;
}

+ 1
- 1
tests/testbench/com/vaadin/tests/components/loginform/LoginFormWithMultipleWindows.java 查看文件

@@ -11,7 +11,7 @@ import com.vaadin.ui.Root;
public class LoginFormWithMultipleWindows extends Application {

@Override
protected Root createRoot(WrappedRequest request) {
protected Root getRoot(WrappedRequest request) {
return new LoginFormWindow();
}


+ 47
- 0
tests/testbench/com/vaadin/tests/components/root/LazyInitRoots.java 查看文件

@@ -0,0 +1,47 @@
package com.vaadin.tests.components.root;

import com.vaadin.Application;
import com.vaadin.RootRequiresMoreInformation;
import com.vaadin.terminal.ExternalResource;
import com.vaadin.terminal.WrappedRequest;
import com.vaadin.terminal.WrappedRequest.BrowserDetails;
import com.vaadin.ui.Label;
import com.vaadin.ui.Link;
import com.vaadin.ui.Root;
import com.vaadin.ui.VerticalLayout;

public class LazyInitRoots extends Application {

@Override
public Root getRoot(WrappedRequest request)
throws RootRequiresMoreInformation {
if (request.getParameter("lazyCreate") != null) {
BrowserDetails browserDetails = request.getBrowserDetails();
if (browserDetails == null) {
throw new RootRequiresMoreInformation();
} else {
VerticalLayout content = new VerticalLayout();
content.addComponent(new Label(browserDetails.getUriFragmet()));
return new Root(content);
}
} else {
VerticalLayout content = new VerticalLayout();
Link lazyCreateLink = new Link("Open lazyCreate root",
new ExternalResource(getURL() + "?lazyCreate"));
lazyCreateLink.setTargetName("_blank");
content.addComponent(lazyCreateLink);
return new Root(content);
}
}

protected String getDescription() {
// TODO Auto-generated method stub
return null;
}

protected Integer getTicketNumber() {
// TODO Auto-generated method stub
return null;
}

}

Loading…
取消
儲存