aboutsummaryrefslogtreecommitdiffstats
path: root/src/com/vaadin/terminal/gwt/server/AjaxPageHandler.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/vaadin/terminal/gwt/server/AjaxPageHandler.java')
-rw-r--r--src/com/vaadin/terminal/gwt/server/AjaxPageHandler.java490
1 files changed, 300 insertions, 190 deletions
diff --git a/src/com/vaadin/terminal/gwt/server/AjaxPageHandler.java b/src/com/vaadin/terminal/gwt/server/AjaxPageHandler.java
index 6a9a35255e..b301a0c801 100644
--- a/src/com/vaadin/terminal/gwt/server/AjaxPageHandler.java
+++ b/src/com/vaadin/terminal/gwt/server/AjaxPageHandler.java
@@ -9,6 +9,7 @@ import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StringWriter;
+import java.io.Writer;
import javax.servlet.http.HttpServletResponse;
@@ -16,6 +17,8 @@ import com.vaadin.Application;
import com.vaadin.RootRequiresMoreInformation;
import com.vaadin.external.json.JSONException;
import com.vaadin.external.json.JSONObject;
+import com.vaadin.terminal.DeploymentConfiguration;
+import com.vaadin.terminal.PaintException;
import com.vaadin.terminal.RequestHandler;
import com.vaadin.terminal.WrappedRequest;
import com.vaadin.terminal.WrappedResponse;
@@ -32,6 +35,90 @@ public abstract class AjaxPageHandler implements RequestHandler {
*/
protected abstract AbstractCommunicationManager getCommunicationManager();
+ protected class AjaxPageContext {
+ private final WrappedResponse response;
+ private final WrappedRequest request;
+ private final Application application;
+ private final int rootId;
+
+ private Writer writer;
+ private Root root;
+ private String widgetsetName;
+ private String themeName;
+ private String appId;
+
+ private boolean rootFetched = false;
+
+ public AjaxPageContext(WrappedResponse response,
+ WrappedRequest request, Application application, int rootId) {
+ this.response = response;
+ this.request = request;
+ this.application = application;
+ this.rootId = rootId;
+ }
+
+ public WrappedResponse getResponse() {
+ return response;
+ }
+
+ public WrappedRequest getRequest() {
+ return request;
+ }
+
+ public Application getApplication() {
+ return application;
+ }
+
+ public Writer getWriter() throws IOException {
+ if (writer == null) {
+ response.setContentType("text/html");
+ writer = new BufferedWriter(new OutputStreamWriter(
+ response.getOutputStream(), "UTF-8"));
+ }
+ return writer;
+ }
+
+ public int getRootId() {
+ return rootId;
+ }
+
+ public Root getRoot() {
+ if (!rootFetched) {
+ root = Root.getCurrentRoot();
+ rootFetched = true;
+ }
+ return root;
+ }
+
+ public String getWidgetsetName() {
+ if (widgetsetName == null) {
+ Root root = getRoot();
+ if (root != null) {
+ widgetsetName = getWidgetsetForRoot(this);
+ }
+ }
+ return widgetsetName;
+ }
+
+ public String getThemeName() {
+ if (themeName == null) {
+ Root root = getRoot();
+ if (root != null) {
+ themeName = findAndEscapeThemeName(this);
+ }
+ }
+ return themeName;
+ }
+
+ public String getAppId() {
+ if (appId == null) {
+ appId = getApplicationId(this);
+ }
+ return appId;
+ }
+
+ }
+
public boolean handleRequest(Application application,
WrappedRequest request, WrappedResponse response)
throws IOException {
@@ -62,88 +149,63 @@ public abstract class AjaxPageHandler implements RequestHandler {
protected final void writeAjaxPage(WrappedRequest request,
WrappedResponse response, Application application, int rootId)
throws IOException, JSONException {
- final BufferedWriter page = new BufferedWriter(new OutputStreamWriter(
- response.getOutputStream(), "UTF-8"));
- Root root = Root.getCurrentRoot();
+ AjaxPageContext context = createContext(request, response, application,
+ rootId);
- String title = ((root == null || root.getCaption() == null) ? "Vaadin "
- + AbstractApplicationServlet.VERSION_MAJOR : root.getCaption());
+ DeploymentConfiguration deploymentConfiguration = request
+ .getDeploymentConfiguration();
- /* Fetch relative url to application */
- // don't use server and port in uri. It may cause problems with some
- // virtual server configurations which lose the server name
- String appUrl = application.getURL().getPath();
- if (appUrl.endsWith("/")) {
- appUrl = appUrl.substring(0, appUrl.length() - 1);
+ boolean standalone = deploymentConfiguration.isStandalone(request);
+ if (standalone) {
+ setAjaxPageHeaders(context);
+ writeAjaxPageHtmlHeadStart(context);
+ writeAjaxPageHtmlHeader(context);
+ writeAjaxPageHtmlBodyStart(context);
}
- String themeName = getThemeForRoot(request, root);
-
- String themeUri = getThemeUri(themeName, request);
-
- setAjaxPageHeaders(response);
- writeAjaxPageHtmlHeadStart(page, request);
- writeAjaxPageHtmlHeader(page, title, themeUri, request);
- writeAjaxPageHtmlBodyStart(page, request);
-
- String appId = appUrl;
- if ("".equals(appUrl)) {
- appId = "ROOT";
- }
- appId = appId.replaceAll("[^a-zA-Z0-9]", "");
- // Add hashCode to the end, so that it is still (sort of) predictable,
- // but indicates that it should not be used in CSS and such:
- int hashCode = appId.hashCode();
- if (hashCode < 0) {
- hashCode = -hashCode;
- }
- appId = appId + "-" + hashCode;
-
- String widgetset = getWidgetsetForRoot(request, root);
-
// TODO include initial UIDL in the scripts?
- writeAjaxPageHtmlVaadinScripts(page, appUrl, themeUri, appId, request,
- application, rootId, widgetset);
+ writeAjaxPageHtmlVaadinScripts(context);
- /*- Add classnames;
- * .v-app
- * .v-app-loading
- * .v-app-<simpleName for app class>
- * .v-theme-<themeName, remove non-alphanum>
- */
-
- String appClass = "v-app-" + getApplicationCSSClassName(application);
+ writeAjaxPageHtmlMainDiv(context);
- String themeClass = "";
- if (themeName != null) {
- themeClass = "v-theme-" + themeName.replaceAll("[^a-zA-Z0-9]", "");
- } else {
- themeClass = "v-theme-"
- + AbstractApplicationServlet.getDefaultTheme().replaceAll(
- "[^a-zA-Z0-9]", "");
+ Writer page = context.getWriter();
+ if (standalone) {
+ page.write("</body>\n</html>\n");
}
- String classNames = "v-app " + themeClass + " " + appClass;
-
- writeAjaxPageHtmlMainDiv(page, appId, classNames, request);
+ page.close();
+ }
- page.write("</body>\n</html>\n");
+ public AjaxPageContext createContext(WrappedRequest request,
+ WrappedResponse response, Application application, int rootId) {
+ AjaxPageContext context = new AjaxPageContext(response, request,
+ application, rootId);
+ return context;
+ }
- page.close();
+ protected String getMainDivStyle(AjaxPageContext context) {
+ return null;
}
- public String getWidgetsetForRoot(WrappedRequest request, Root root) {
- if (root == null) {
- // Defer widgetset selection
- return null;
- }
+ /**
+ * Creates and returns a unique ID for the DIV where the application is to
+ * be rendered.
+ *
+ * @param context
+ *
+ * @return the id to use in the DOM
+ */
+ protected abstract String getApplicationId(AjaxPageContext context);
+
+ public String getWidgetsetForRoot(AjaxPageContext context) {
+ Root root = context.getRoot();
+ WrappedRequest request = context.getRequest();
String widgetset = root.getApplication().getWidgetsetForRoot(root);
if (widgetset == null) {
- widgetset = getApplicationOrSystemProperty(request,
- AbstractApplicationServlet.PARAMETER_WIDGETSET,
- AbstractApplicationServlet.DEFAULT_WIDGETSET);
+ widgetset = request.getDeploymentConfiguration()
+ .getConfiguredWidgetset(request);
}
widgetset = AbstractApplicationServlet.stripSpecialChars(widgetset);
@@ -158,16 +220,42 @@ public abstract class AjaxPageHandler implements RequestHandler {
* the div element into which the actual Vaadin application will be
* rendered.
*
- * @param page
- * @param appId
- * @param classNames
- * @param request
+ * @param context
+ *
* @throws IOException
*/
- protected void writeAjaxPageHtmlMainDiv(final BufferedWriter page,
- String appId, String classNames, WrappedRequest request)
+ protected void writeAjaxPageHtmlMainDiv(AjaxPageContext context)
throws IOException {
- page.write("<div id=\"" + appId + "\" class=\"" + classNames + "\">");
+ Writer page = context.getWriter();
+ String style = getMainDivStyle(context);
+ String themeName = context.getThemeName();
+
+ /*- Add classnames;
+ * .v-app
+ * .v-app-loading
+ * .v-app-<simpleName for app class>
+ * .v-theme-<themeName, remove non-alphanum>
+ */
+
+ String appClass = "v-app-"
+ + getApplicationCSSClassName(context.getApplication());
+
+ String themeClass = "";
+ if (themeName != null) {
+ themeClass = "v-theme-" + themeName.replaceAll("[^a-zA-Z0-9]", "");
+ } else {
+ themeClass = "v-theme-"
+ + AbstractApplicationServlet.getDefaultTheme().replaceAll(
+ "[^a-zA-Z0-9]", "");
+ }
+
+ String classNames = "v-app " + themeClass + " " + appClass;
+
+ if (style != null && style.length() != 0) {
+ style = " style=\"" + style + "\"";
+ }
+ page.write("<div id=\"" + context.getAppId() + "\" class=\""
+ + classNames + "\"" + style + ">");
page.write("<div class=\"v-app-loading\"></div>");
page.write("</div>\n");
page.write("<noscript>" + getNoScriptMessage() + "</noscript>");
@@ -203,12 +291,11 @@ public abstract class AjaxPageHandler implements RequestHandler {
* <p>
* Override this method if you want to add some custom html to the page.
*
- * @param page
- * @param request
* @throws IOException
*/
- protected void writeAjaxPageHtmlBodyStart(final BufferedWriter page,
- final WrappedRequest request) throws IOException {
+ protected void writeAjaxPageHtmlBodyStart(AjaxPageContext context)
+ throws IOException {
+ Writer page = context.getWriter();
page.write("\n</head>\n<body scroll=\"auto\" class=\""
+ ApplicationConnection.GENERATED_BODY_CLASSNAME + "\">\n");
}
@@ -219,29 +306,24 @@ public abstract class AjaxPageHandler implements RequestHandler {
* <p>
* Override this method if you want to add some custom html around scripts.
*
- * @param page
- * @param appUrl
- * @param themeUri
- * @param appId
- * @param request
- * @param application
- * @param rootId
+ * @param context
+ *
* @throws IOException
* @throws JSONException
*/
- 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();
+ protected void writeAjaxPageHtmlVaadinScripts(AjaxPageContext context)
+ throws IOException, JSONException {
+ WrappedRequest request = context.getRequest();
+ Writer page = context.getWriter();
- String widgetsetBase = staticFileLocation + "/"
- + AbstractApplicationServlet.WIDGETSET_DIRECTORY_PATH;
+ DeploymentConfiguration deploymentConfiguration = request
+ .getDeploymentConfiguration();
+ String staticFileLocation = deploymentConfiguration
+ .getStaticFileLocation(request);
- // Get system messages
- Application.SystemMessages systemMessages = AbstractApplicationServlet
- .getSystemMessages(application.getClass());
+ page.write("<iframe tabIndex=\"-1\" id=\"__gwt_historyFrame\" "
+ + "style=\"position:absolute;width:0;height:0;border:0;overflow:"
+ + "hidden;\" src=\"javascript:false\"></iframe>");
page.write("<script type=\"text/javascript\" src=\"");
page.write(staticFileLocation);
@@ -250,33 +332,90 @@ public abstract class AjaxPageHandler implements RequestHandler {
page.write("<script type=\"text/javascript\">\n");
page.write("//<![CDATA[\n");
- JSONObject defaults = new JSONObject();
- JSONObject appConfig = new JSONObject();
+ writeMainScriptTagContents(context);
+ page.write("//]]>\n</script>\n");
+ }
+
+ protected void writeMainScriptTagContents(AjaxPageContext context)
+ throws JSONException, IOException {
+ JSONObject defaults = getDefaultParameters(context);
+ JSONObject appConfig = getApplicationParameters(context);
- boolean isDebug = !application.isProductionMode();
+ boolean isDebug = !context.getApplication().isProductionMode();
+ Writer page = context.getWriter();
+
+ page.write("vaadin.setDefaults(");
+ printJsonObject(page, defaults, isDebug);
+ page.write(");\n");
+
+ page.write("vaadin.initApplication(\"");
+ page.write(context.getAppId());
+ page.write("\",");
+ printJsonObject(page, appConfig, isDebug);
+ page.write(");\n");
+ }
+
+ private static void printJsonObject(Writer page, JSONObject jsonObject,
+ boolean isDebug) throws IOException, JSONException {
if (isDebug) {
- defaults.put("debug", true);
+ page.write(jsonObject.toString(4));
+ } else {
+ page.write(jsonObject.toString());
}
+ }
- page.write("document.write('<iframe tabIndex=\"-1\" id=\"__gwt_historyFrame\" "
- + "style=\"position:absolute;width:0;height:0;border:0;overflow:"
- + "hidden;\" src=\"javascript:false\"></iframe>');\n");
+ protected JSONObject getApplicationParameters(AjaxPageContext context)
+ throws JSONException, PaintException {
+ Application application = context.getApplication();
+ int rootId = context.getRootId();
- defaults.put("appUri", appUrl);
+ JSONObject appConfig = new JSONObject();
appConfig.put(ApplicationConnection.ROOT_ID_PARAMETER, rootId);
- if (isStandalone()) {
- defaults.put("standalone", true);
+ if (context.getThemeName() != null) {
+ appConfig.put("themeUri",
+ getThemeUri(context, context.getThemeName()));
}
- appConfig.put("themeUri", themeUri);
-
JSONObject versionInfo = new JSONObject();
versionInfo.put("vaadinVersion", AbstractApplicationServlet.VERSION);
versionInfo.put("applicationVersion", application.getVersion());
appConfig.put("versionInfo", versionInfo);
+ appConfig.put("widgetset", context.getWidgetsetName());
+
+ if (application.isRootInitPending(rootId)) {
+ appConfig.put("initPending", true);
+ } else {
+ // write the initial UIDL into the config
+ AbstractCommunicationManager manager = getCommunicationManager();
+ Root root = Root.getCurrentRoot();
+ manager.makeAllPaintablesDirty(root);
+ StringWriter sWriter = new StringWriter();
+ PrintWriter pWriter = new PrintWriter(sWriter);
+ pWriter.print("{");
+ if (manager.isXSRFEnabled(application)) {
+ pWriter.print(manager.getSecurityKeyUIDL(context.getRequest()));
+ }
+ manager.writeUidlResponce(null, true, pWriter, root, false);
+ pWriter.print("}");
+ appConfig.put("uidl", sWriter.toString());
+ }
+
+ return appConfig;
+ }
+
+ protected JSONObject getDefaultParameters(AjaxPageContext context)
+ throws JSONException {
+ JSONObject defaults = new JSONObject();
+
+ WrappedRequest request = context.getRequest();
+ Application application = context.getApplication();
+
+ // Get system messages
+ Application.SystemMessages systemMessages = AbstractApplicationServlet
+ .getSystemMessages(application.getClass());
if (systemMessages != null) {
// Write the CommunicationError -message to client
JSONObject comErrMsg = new JSONObject();
@@ -298,75 +437,42 @@ public abstract class AjaxPageHandler implements RequestHandler {
defaults.put("authErrMsg", authErrMsg);
}
+ DeploymentConfiguration deploymentConfiguration = request
+ .getDeploymentConfiguration();
+ String staticFileLocation = deploymentConfiguration
+ .getStaticFileLocation(request);
+ String widgetsetBase = staticFileLocation + "/"
+ + AbstractApplicationServlet.WIDGETSET_DIRECTORY_PATH;
defaults.put("widgetsetBase", widgetsetBase);
- appConfig.put("widgetset", widgetset);
-
- if (application.isRootInitPending(rootId)) {
- appConfig.put("initPending", true);
- } else {
- // write the initial UIDL into the config
- AbstractCommunicationManager manager = getCommunicationManager();
- Root root = Root.getCurrentRoot();
- manager.makeAllPaintablesDirty(root);
- StringWriter sWriter = new StringWriter();
- PrintWriter pWriter = new PrintWriter(sWriter);
- pWriter.print("{");
- if (manager.isXSRFEnabled(application)) {
- pWriter.print(manager.getSecurityKeyUIDL(request));
- }
- manager.writeUidlResponce(null, true, pWriter, root, false);
- pWriter.print("}");
- appConfig.put("uidl", sWriter.toString());
- }
-
- page.write("vaadin.setDefaults(");
- if (isDebug) {
- page.write(defaults.toString(4));
- } else {
- page.write(defaults.toString());
+ if (!application.isProductionMode()) {
+ defaults.put("debug", true);
}
- page.write(");\n");
- page.write("vaadin.initApplication(\"");
- page.write(appId);
- page.write("\",");
- if (isDebug) {
- page.write(appConfig.toString(4));
- } else {
- page.write(appConfig.toString());
+ if (deploymentConfiguration.isStandalone(request)) {
+ defaults.put("standalone", true);
}
- page.write(");\n");
- page.write("//]]>\n</script>\n");
- }
- protected abstract String getApplicationOrSystemProperty(
- WrappedRequest request, String parameter, String defaultValue);
+ defaults.put("appUri", getAppUri(context));
- /**
- * @return true if the served application is considered to be the only or
- * main content of the host page. E.g. various embedding solutions
- * should override this to false.
- */
- protected boolean isStandalone() {
- return true;
+ return defaults;
}
+ protected abstract String getAppUri(AjaxPageContext context);
+
/**
* Method to write the contents of head element in html kickstart page.
* <p>
* Override this method if you want to add some custom html to the header of
* the page.
*
- * @param page
- * @param title
- * @param themeUri
- * @param request
* @throws IOException
*/
- protected void writeAjaxPageHtmlHeader(final BufferedWriter page,
- String title, String themeUri, final WrappedRequest request)
+ protected void writeAjaxPageHtmlHeader(AjaxPageContext context)
throws IOException {
+ Writer page = context.getWriter();
+ String themeName = context.getThemeName();
+
page.write("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>\n");
// Chrome frame in all versions of IE (only if Chrome frame is
@@ -377,13 +483,18 @@ public abstract class AjaxPageHandler implements RequestHandler {
+ "html, body {height:100%;margin:0;}</style>");
// Add favicon links
- if (themeUri != null) {
+ if (themeName != null) {
+ String themeUri = getThemeUri(context, themeName);
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\" />");
}
+ Root root = context.getRoot();
+ String title = ((root == null || root.getCaption() == null) ? "Vaadin "
+ + AbstractApplicationServlet.VERSION_MAJOR : root.getCaption());
+
page.write("<title>"
+ AbstractApplicationServlet.safeEscapeForHtml(title)
+ "</title>");
@@ -394,9 +505,11 @@ public abstract class AjaxPageHandler implements RequestHandler {
* <p>
* Override this method if you need to customize http headers of the page.
*
- * @param response
+ * @param context
*/
- protected void setAjaxPageHeaders(WrappedResponse response) {
+ protected void setAjaxPageHeaders(AjaxPageContext context) {
+ WrappedResponse response = context.getResponse();
+
// Window renders are not cacheable
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Pragma", "no-cache");
@@ -413,12 +526,13 @@ public abstract class AjaxPageHandler implements RequestHandler {
* Override this method if you want to add some custom html to the very
* beginning of the page.
*
- * @param page
- * @param request
+ * @param context
* @throws IOException
*/
- protected void writeAjaxPageHtmlHeadStart(final BufferedWriter page,
- final WrappedRequest request) throws IOException {
+ protected void writeAjaxPageHtmlHeadStart(AjaxPageContext context)
+ throws IOException {
+ Writer page = context.getWriter();
+
// write html header
page.write("<!DOCTYPE html PUBLIC \"-//W3C//DTD "
+ "XHTML 1.0 Transitional//EN\" "
@@ -435,45 +549,41 @@ public abstract class AjaxPageHandler implements RequestHandler {
* A portal-wide default theme is fetched from the portal shared resource
* directory (if any), other themes from the portlet.
*
+ * @param context
* @param themeName
- * @param request
+ *
* @return
*/
- public String getThemeUri(String themeName, WrappedRequest request) {
- if (themeName == null) {
- return null;
- }
- final String staticFilePath = request.getStaticFileLocation();
+ public String getThemeUri(AjaxPageContext context, String themeName) {
+ WrappedRequest request = context.getRequest();
+ final String staticFilePath = request.getDeploymentConfiguration()
+ .getStaticFileLocation(request);
return staticFilePath + "/"
+ AbstractApplicationServlet.THEME_DIRECTORY_PATH + themeName;
}
/**
- * Returns the theme for given request/root
+ * Override if required
*
- * @param request
- * @param root
+ * @param context
* @return
*/
- public String getThemeForRoot(WrappedRequest request, Root root) {
- if (root == null) {
- return null;
- }
- // Finds theme name
- String themeName;
-
- if (request
- .getParameter(AbstractApplicationServlet.URL_PARAMETER_THEME) != null) {
- themeName = request
- .getParameter(AbstractApplicationServlet.URL_PARAMETER_THEME);
- } else {
- themeName = root.getApplication().getThemeForRoot(root);
- }
+ public String getThemeName(AjaxPageContext context) {
+ return context.getApplication().getThemeForRoot(context.getRoot());
+ }
+ /**
+ * Don not override.
+ *
+ * @param context
+ * @return
+ */
+ public String findAndEscapeThemeName(AjaxPageContext context) {
+ String themeName = getThemeName(context);
if (themeName == null) {
- // no explicit theme for root defined
- // using the default theme defined by Vaadin
- themeName = AbstractApplicationServlet.getDefaultTheme();
+ WrappedRequest request = context.getRequest();
+ themeName = request.getDeploymentConfiguration()
+ .getConfiguredTheme(request);
}
// XSS preventation, theme names shouldn't contain special chars anyway.