summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLeif Åstrand <leif@vaadin.com>2011-11-22 17:40:51 +0200
committerLeif Åstrand <leif@vaadin.com>2011-11-22 17:40:51 +0200
commitdc80599cb99066b8fb8135f580efa631f28f13d2 (patch)
treec240db5ce57954554977a10d99beef281defa8d7 /src
parent3bbb808f7f5d9a0b7cdf5454fd3b5843c5b78fe4 (diff)
downloadvaadin-framework-dc80599cb99066b8fb8135f580efa631f28f13d2.tar.gz
vaadin-framework-dc80599cb99066b8fb8135f580efa631f28f13d2.zip
Move ajax page generation code to AjaxPageHandler
Diffstat (limited to 'src')
-rw-r--r--src/com/vaadin/Application.java5
-rw-r--r--src/com/vaadin/terminal/WrappedRequest.java2
-rw-r--r--src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java468
-rw-r--r--src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java23
-rw-r--r--src/com/vaadin/terminal/gwt/server/AjaxPageHandler.java411
-rw-r--r--src/com/vaadin/terminal/gwt/server/WrappedHttpServletRequest.java4
-rw-r--r--src/com/vaadin/terminal/gwt/server/WrappedPortletRequest.java4
7 files changed, 447 insertions, 470 deletions
diff --git a/src/com/vaadin/Application.java b/src/com/vaadin/Application.java
index 3a828636a0..c4a370b8d9 100644
--- a/src/com/vaadin/Application.java
+++ b/src/com/vaadin/Application.java
@@ -1623,6 +1623,11 @@ public class Application implements Terminal.ErrorListener, Serializable {
return null;
}
+ public String getWidgetsetForRoot(Root root) {
+ // TODO Get widgetset from root annotation
+ return null;
+ }
+
public boolean handleRequest(WrappedRequest request,
WrappedResponse response) throws IOException {
for (RequestHandler handler : new ArrayList<RequestHandler>(
diff --git a/src/com/vaadin/terminal/WrappedRequest.java b/src/com/vaadin/terminal/WrappedRequest.java
index b9cc18d3e6..5ab11a7374 100644
--- a/src/com/vaadin/terminal/WrappedRequest.java
+++ b/src/com/vaadin/terminal/WrappedRequest.java
@@ -63,4 +63,6 @@ public interface WrappedRequest extends Serializable {
public String getContentType();
+ public String getStaticFileLocation();
+
}
diff --git a/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java b/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java
index 0593764c52..401f1e2c68 100644
--- a/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java
+++ b/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java
@@ -18,7 +18,6 @@ import java.net.URL;
import java.security.GeneralSecurityException;
import java.util.Arrays;
import java.util.Collection;
-import java.util.Date;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
@@ -302,7 +301,7 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
* the Default to be used.
* @return String value or default if not found
*/
- private String getApplicationOrSystemProperty(String parameterName,
+ String getApplicationOrSystemProperty(String parameterName,
String defaultValue) {
String val = null;
@@ -854,36 +853,6 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
}
/**
- * Returns the theme for given request/root
- *
- * @param request
- * @param root
- * @return
- */
- private String getThemeForRoot(HttpServletRequest request, Root root) {
- // Finds theme name
- String themeName;
-
- if (request.getParameter(URL_PARAMETER_THEME) != null) {
- themeName = request.getParameter(URL_PARAMETER_THEME);
- } else {
- themeName = root.getApplication().getThemeForRoot(root);
- }
-
- if (themeName == null) {
- // no explicit theme for root defined
- // using the default theme defined by Vaadin
- themeName = getDefaultTheme();
- }
-
- // XSS preventation, theme names shouldn't contain special chars anyway.
- // The servlet denies them via url parameter.
- themeName = stripSpecialChars(themeName);
-
- return themeName;
- }
-
- /**
* A helper method to strip away characters that might somehow be used for
* XSS attacs. Leaves at least alphanumeric characters intact. Also removes
* eg. ( and ), so values should be safe in javascript too.
@@ -1344,13 +1313,25 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
* @return
*/
protected SystemMessages getSystemMessages() {
+ Class<? extends Application> appCls = null;
try {
- Class<? extends Application> appCls = getApplicationClass();
- Method m = appCls.getMethod("getSystemMessages", (Class[]) null);
- return (Application.SystemMessages) m.invoke(null, (Object[]) null);
+ appCls = getApplicationClass();
} catch (ClassNotFoundException e) {
- // This should never happen
+ // Previous comment claimed that this should never happen
throw new SystemMessageException(e);
+ }
+ return getSystemMessages(appCls);
+ }
+
+ public static SystemMessages getSystemMessages(
+ Class<? extends Application> appCls) {
+ try {
+ if (appCls != null) {
+ Method m = appCls
+ .getMethod("getSystemMessages", (Class[]) null);
+ return (Application.SystemMessages) m.invoke(null,
+ (Object[]) null);
+ }
} catch (SecurityException e) {
throw new SystemMessageException(
"Application.getSystemMessage() should be static public", e);
@@ -1468,421 +1449,6 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
}
/**
- * This method writes the html host page (aka kickstart page) that starts
- * the actual Vaadin application.
- * <p>
- * If one needs to override parts of the host page, it is suggested that one
- * overrides on of several submethods which are called by this method:
- * <ul>
- * <li> {@link #setAjaxPageHeaders(HttpServletResponse)}
- * <li>
- * {@link #writeAjaxPageHtmlHeadStart(BufferedWriter, HttpServletRequest)}
- * <li>
- * {@link #writeAjaxPageHtmlHeader(BufferedWriter, String, String, HttpServletRequest)}
- * <li>
- * {@link #writeAjaxPageHtmlBodyStart(BufferedWriter, HttpServletRequest)}
- * <li>
- * {@link #writeAjaxPageHtmlVaadinScripts(Root, String, Application, BufferedWriter, String, String, String, HttpServletRequest)}
- * <li>
- * {@link #writeAjaxPageHtmlMainDiv(BufferedWriter, String, String, HttpServletRequest)}
- * <li> {@link #writeAjaxPageHtmlBodyEnd(BufferedWriter)}
- * </ul>
- *
- * @param request
- * the HTTP request.
- * @param response
- * the HTTP response to write to.
- * @param out
- * @param unhandledParameters
- * @param root
- * @param terminalType
- * @param theme
- * @throws IOException
- * if the writing failed due to input/output error.
- * @throws MalformedURLException
- * if the application is denied access the persistent data store
- * represented by the given URL.
- */
- protected void writeAjaxPage(HttpServletRequest request,
- HttpServletResponse response, Root root, Application application)
- throws IOException, MalformedURLException, ServletException {
-
- final BufferedWriter page = new BufferedWriter(new OutputStreamWriter(
- response.getOutputStream(), "UTF-8"));
-
- String title = ((root.getCaption() == null) ? "Vaadin 6" : root
- .getCaption());
-
- /* 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 = getApplicationUrl(request).getPath();
- if (appUrl.endsWith("/")) {
- appUrl = appUrl.substring(0, appUrl.length() - 1);
- }
-
- 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;
-
- writeAjaxPageHtmlVaadinScripts(themeName, application, page, appUrl,
- themeUri, appId, request, root.getRootId());
-
- /*- Add classnames;
- * .v-app
- * .v-app-loading
- * .v-app-<simpleName for app class>
- * .v-theme-<themeName, remove non-alphanum>
- */
-
- String appClass = "v-app-" + getApplicationCSSClassName();
-
- String themeClass = "";
- if (themeName != null) {
- themeClass = "v-theme-" + themeName.replaceAll("[^a-zA-Z0-9]", "");
- } else {
- themeClass = "v-theme-"
- + getDefaultTheme().replaceAll("[^a-zA-Z0-9]", "");
- }
-
- String classNames = "v-app " + themeClass + " " + appClass;
-
- writeAjaxPageHtmlMainDiv(page, appId, classNames, request);
-
- page.write("</body>\n</html>\n");
-
- page.close();
-
- }
-
- /**
- * Returns the application class identifier for use in the application CSS
- * class name in the root DIV. The application CSS class name is of form
- * "v-app-"+getApplicationCSSClassName().
- *
- * This method should normally not be overridden.
- *
- * @return The CSS class name to use in combination with "v-app-".
- */
- protected String getApplicationCSSClassName() {
- try {
- return getApplicationClass().getSimpleName();
- } catch (ClassNotFoundException e) {
- logger.log(Level.WARNING, "getApplicationCSSClassName failed", e);
- return "unknown";
- }
- }
-
- /**
- * Get the URI for the application theme.
- *
- * A portal-wide default theme is fetched from the portal shared resource
- * directory (if any), other themes from the portlet.
- *
- * @param themeName
- * @param request
- * @return
- */
- private String getThemeUri(String themeName, HttpServletRequest request) {
- final String staticFilePath = getWebApplicationsStaticFileLocation(request);
- return staticFilePath + "/" + THEME_DIRECTORY_PATH + themeName;
- }
-
- /**
- * Method to write the div element into which that actual Vaadin application
- * is rendered.
- * <p>
- * Override this method if you want to add some custom html around around
- * the div element into which the actual Vaadin application will be
- * rendered.
- *
- * @param page
- * @param appId
- * @param classNames
- * @param request
- * @throws IOException
- */
- protected void writeAjaxPageHtmlMainDiv(final BufferedWriter page,
- String appId, String classNames, HttpServletRequest request)
- throws IOException {
- page.write("<div id=\"" + appId + "\" class=\"" + classNames + "\">");
- page.write("<div class=\"v-app-loading\"></div>");
- page.write("</div>\n");
- page.write("<noscript>" + getNoScriptMessage() + "</noscript>");
- }
-
- /**
- * Method to write the script part of the page which loads needed Vaadin
- * scripts and themes.
- * <p>
- * Override this method if you want to add some custom html around scripts.
- *
- * @param themeName
- * @param application
- * @param page
- * @param appUrl
- * @param themeUri
- * @param appId
- * @param request
- * @param rootId
- * @throws ServletException
- * @throws IOException
- */
- protected void writeAjaxPageHtmlVaadinScripts(
- // Window window,
- String themeName, Application application,
- final BufferedWriter page, String appUrl, String themeUri,
- String appId, HttpServletRequest request, int rootId)
- throws ServletException, IOException {
-
- String widgetset = getApplicationOrSystemProperty(PARAMETER_WIDGETSET,
- DEFAULT_WIDGETSET);
- String widgetsetBasePath = getWebApplicationsStaticFileLocation(request);
-
- widgetset = stripSpecialChars(widgetset);
-
- final String widgetsetFilePath = widgetsetBasePath + "/"
- + WIDGETSET_DIRECTORY_PATH + widgetset + "/" + widgetset
- + ".nocache.js?" + new Date().getTime();
-
- // Get system messages
- Application.SystemMessages systemMessages = null;
- try {
- systemMessages = getSystemMessages();
- } catch (SystemMessageException e) {
- // failing to get the system messages is always a problem
- throw new ServletException("CommunicationError!", e);
- }
-
- page.write("<script type=\"text/javascript\">\n");
- page.write("//<![CDATA[\n");
- page.write("if(!vaadin || !vaadin.vaadinConfigurations) {\n "
- + "if(!vaadin) { var vaadin = {}} \n"
- + "vaadin.vaadinConfigurations = {};\n"
- + "if (!vaadin.themesLoaded) { vaadin.themesLoaded = {}; }\n");
- if (!isProductionMode()) {
- page.write("vaadin.debug = true;\n");
- }
- 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");
- page.write("document.write(\"<script language='javascript' src='"
- + widgetsetFilePath + "'><\\/script>\");\n}\n");
-
- page.write("vaadin.vaadinConfigurations[\"" + appId + "\"] = {");
- page.write("appUri:'" + appUrl + "', ");
-
- page.write(ApplicationConnection.ROOT_ID_PARAMETER + ": " + rootId
- + ", ");
-
- if (isStandalone()) {
- page.write("standalone: true, ");
- }
- page.write("themeUri:");
- page.write(themeUri != null ? "\"" + themeUri + "\"" : "null");
- page.write(", versionInfo : {vaadinVersion:\"");
- page.write(VERSION);
- page.write("\",applicationVersion:\"");
- page.write(JsonPaintTarget.escapeJSON(application.getVersion()));
- page.write("\"}");
- if (systemMessages != null) {
- // Write the CommunicationError -message to client
- String caption = systemMessages.getCommunicationErrorCaption();
- if (caption != null) {
- caption = "\"" + JsonPaintTarget.escapeJSON(caption) + "\"";
- }
- String message = systemMessages.getCommunicationErrorMessage();
- if (message != null) {
- message = "\"" + JsonPaintTarget.escapeJSON(message) + "\"";
- }
- String url = systemMessages.getCommunicationErrorURL();
- if (url != null) {
- url = "\"" + JsonPaintTarget.escapeJSON(url) + "\"";
- }
-
- page.write(",\"comErrMsg\": {" + "\"caption\":" + caption + ","
- + "\"message\" : " + message + "," + "\"url\" : " + url
- + "}");
-
- // Write the AuthenticationError -message to client
- caption = systemMessages.getAuthenticationErrorCaption();
- if (caption != null) {
- caption = "\"" + JsonPaintTarget.escapeJSON(caption) + "\"";
- }
- message = systemMessages.getAuthenticationErrorMessage();
- if (message != null) {
- message = "\"" + JsonPaintTarget.escapeJSON(message) + "\"";
- }
- url = systemMessages.getAuthenticationErrorURL();
- if (url != null) {
- url = "\"" + JsonPaintTarget.escapeJSON(url) + "\"";
- }
-
- page.write(",\"authErrMsg\": {" + "\"caption\":" + caption + ","
- + "\"message\" : " + message + "," + "\"url\" : " + url
- + "}");
- }
- page.write("};\n//]]>\n</script>\n");
-
- if (themeName != null) {
- // Custom theme's stylesheet, load only once, in different
- // script
- // tag to be dominate styles injected by widget
- // set
- page.write("<script type=\"text/javascript\">\n");
- page.write("//<![CDATA[\n");
- page.write("if(!vaadin.themesLoaded['" + themeName + "']) {\n");
- page.write("var stylesheet = document.createElement('link');\n");
- page.write("stylesheet.setAttribute('rel', 'stylesheet');\n");
- page.write("stylesheet.setAttribute('type', 'text/css');\n");
- page.write("stylesheet.setAttribute('href', '" + themeUri
- + "/styles.css');\n");
- page.write("document.getElementsByTagName('head')[0].appendChild(stylesheet);\n");
- page.write("vaadin.themesLoaded['" + themeName + "'] = true;\n}\n");
- page.write("//]]>\n</script>\n");
- }
-
- // Warn if the widgetset has not been loaded after 15 seconds on
- // inactivity
- page.write("<script type=\"text/javascript\">\n");
- page.write("//<![CDATA[\n");
- page.write("setTimeout('if (typeof " + widgetset.replace('.', '_')
- + " == \"undefined\") {alert(\"Failed to load the widgetset: "
- + widgetsetFilePath + "\")};',15000);\n" + "//]]>\n</script>\n");
- }
-
- /**
- * @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;
- }
-
- /**
- *
- * Method to open the body tag of the html kickstart page.
- * <p>
- * This method is responsible for closing the head tag and opening the body
- * tag.
- * <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 HttpServletRequest request) throws IOException {
- page.write("\n</head>\n<body scroll=\"auto\" class=\""
- + ApplicationConnection.GENERATED_BODY_CLASSNAME + "\">\n");
- }
-
- /**
- * 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 HttpServletRequest request)
- throws IOException {
- page.write("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>\n");
-
- WebBrowser browser = getApplicationContext(request.getSession())
- .getBrowser();
- if (browser.isIE()) {
- // Chrome frame in all versions of IE (only if Chrome frame is
- // installed)
- page.write("<meta http-equiv=\"X-UA-Compatible\" content=\"chrome=1\"/>\n");
- }
-
- page.write("<style type=\"text/css\">"
- + "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\" />");
-
- page.write("<title>" + safeEscapeForHtml(title) + "</title>");
- }
-
- /**
- * Method to write the beginning of the html page.
- * <p>
- * This method is responsible for writing appropriate doc type declarations
- * and to open html and head tags.
- * <p>
- * Override this method if you want to add some custom html to the very
- * beginning of the page.
- *
- * @param page
- * @param request
- * @throws IOException
- */
- protected void writeAjaxPageHtmlHeadStart(final BufferedWriter page,
- final HttpServletRequest request) throws IOException {
- // write html header
- page.write("<!DOCTYPE html PUBLIC \"-//W3C//DTD "
- + "XHTML 1.0 Transitional//EN\" "
- + "\"http://www.w3.org/TR/xhtml1/"
- + "DTD/xhtml1-transitional.dtd\">\n");
-
- page.write("<html xmlns=\"http://www.w3.org/1999/xhtml\""
- + ">\n<head>\n");
- }
-
- /**
- * Method to set http request headers for the Vaadin kickstart page.
- * <p>
- * Override this method if you need to customize http headers of the page.
- *
- * @param response
- */
- protected void setAjaxPageHeaders(HttpServletResponse response) {
- // Window renders are not cacheable
- response.setHeader("Cache-Control", "no-cache");
- response.setHeader("Pragma", "no-cache");
- response.setDateHeader("Expires", 0);
- response.setContentType("text/html; charset=UTF-8");
- }
-
- /**
- * Returns a message printed for browsers without scripting support or if
- * browsers scripting support is disabled.
- */
- protected String getNoScriptMessage() {
- return "You have to enable javascript in your browser to use an application built with Vaadin.";
- }
-
- /**
* Gets the current application URL from request.
*
* @param request
diff --git a/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java b/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java
index dd3304d21d..d72015dae4 100644
--- a/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java
+++ b/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java
@@ -41,8 +41,6 @@ import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
-import javax.servlet.ServletException;
-
import com.vaadin.Application;
import com.vaadin.Application.SystemMessages;
import com.vaadin.terminal.PaintException;
@@ -95,21 +93,12 @@ public abstract class AbstractCommunicationManager implements
private static final RequestHandler AJAX_PAGE_HANDLER = new AjaxPageHandler() {
@Override
- protected void writeAjaxPage(WrappedRequest request,
- WrappedResponse response, Root root) throws IOException {
- {
- WrappedHttpServletRequest wrappedServletRequest = (WrappedHttpServletRequest) request;
- try {
- wrappedServletRequest.getServlet().writeAjaxPage(
- wrappedServletRequest.getHttpServletRequest(),
- ((WrappedHttpServletResponse) response)
- .getHttpServletResponse(), root,
- root.getApplication());
- } catch (ServletException e) {
- logger.log(Level.WARNING, e.getLocalizedMessage(), e);
- writeError(response, e);
- }
- }
+ protected String getApplicationOrSystemProperty(
+ WrappedRequest request, String parameter,
+ String defaultValue) {
+ WrappedHttpServletRequest r = (WrappedHttpServletRequest) request;
+ return r.getServlet().getApplicationOrSystemProperty(
+ parameter, defaultValue);
}
};
diff --git a/src/com/vaadin/terminal/gwt/server/AjaxPageHandler.java b/src/com/vaadin/terminal/gwt/server/AjaxPageHandler.java
index be6b120b56..6975bcbb0a 100644
--- a/src/com/vaadin/terminal/gwt/server/AjaxPageHandler.java
+++ b/src/com/vaadin/terminal/gwt/server/AjaxPageHandler.java
@@ -1,11 +1,16 @@
package com.vaadin.terminal.gwt.server;
+import java.io.BufferedWriter;
import java.io.IOException;
+import java.io.OutputStreamWriter;
+
+import javax.servlet.ServletException;
import com.vaadin.Application;
import com.vaadin.terminal.RequestHandler;
import com.vaadin.terminal.WrappedRequest;
import com.vaadin.terminal.WrappedResponse;
+import com.vaadin.terminal.gwt.client.ApplicationConnection;
import com.vaadin.ui.Root;
public abstract class AjaxPageHandler implements RequestHandler {
@@ -27,8 +32,410 @@ public abstract class AjaxPageHandler implements RequestHandler {
return true;
}
- protected abstract void writeAjaxPage(WrappedRequest request,
- WrappedResponse response, Root root) throws IOException;
+ protected final void writeAjaxPage(WrappedRequest request,
+ WrappedResponse response, Root root) throws IOException {
+ Application application = root.getApplication();
+ final BufferedWriter page = new BufferedWriter(new OutputStreamWriter(
+ response.getOutputStream(), "UTF-8"));
+
+ String title = ((root.getCaption() == null) ? "Vaadin 6" : root
+ .getCaption());
+
+ /* 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);
+ }
+
+ 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;
+
+ writeAjaxPageHtmlVaadinScripts(themeName, page, appUrl, themeUri,
+ appId, request, root);
+
+ /*- 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);
+
+ 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;
+
+ writeAjaxPageHtmlMainDiv(page, appId, classNames, request);
+
+ page.write("</body>\n</html>\n");
+
+ page.close();
+ }
+
+ /**
+ * Method to write the div element into which that actual Vaadin application
+ * is rendered.
+ * <p>
+ * Override this method if you want to add some custom html around around
+ * the div element into which the actual Vaadin application will be
+ * rendered.
+ *
+ * @param page
+ * @param appId
+ * @param classNames
+ * @param request
+ * @throws IOException
+ */
+ protected void writeAjaxPageHtmlMainDiv(final BufferedWriter page,
+ String appId, String classNames, WrappedRequest request)
+ throws IOException {
+ page.write("<div id=\"" + appId + "\" class=\"" + classNames + "\">");
+ page.write("<div class=\"v-app-loading\"></div>");
+ page.write("</div>\n");
+ page.write("<noscript>" + getNoScriptMessage() + "</noscript>");
+ }
+
+ /**
+ * Returns a message printed for browsers without scripting support or if
+ * browsers scripting support is disabled.
+ */
+ protected String getNoScriptMessage() {
+ return "You have to enable javascript in your browser to use an application built with Vaadin.";
+ }
+
+ /**
+ * Returns the application class identifier for use in the application CSS
+ * class name in the root DIV. The application CSS class name is of form
+ * "v-app-"+getApplicationCSSClassName().
+ *
+ * This method should normally not be overridden.
+ *
+ * @return The CSS class name to use in combination with "v-app-".
+ */
+ protected String getApplicationCSSClassName(Application application) {
+ return application.getClass().getSimpleName();
+ }
+
+ /**
+ *
+ * Method to open the body tag of the html kickstart page.
+ * <p>
+ * This method is responsible for closing the head tag and opening the body
+ * tag.
+ * <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 {
+ page.write("\n</head>\n<body scroll=\"auto\" class=\""
+ + ApplicationConnection.GENERATED_BODY_CLASSNAME + "\">\n");
+ }
+
+ /**
+ * Method to write the script part of the page which loads needed Vaadin
+ * scripts and themes.
+ * <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 rootId
+ * @throws ServletException
+ * @throws IOException
+ */
+ protected void writeAjaxPageHtmlVaadinScripts(String themeName,
+ final BufferedWriter page, String appUrl, String themeUri,
+ String appId, WrappedRequest request, Root root) throws IOException {
+
+ Application application = root.getApplication();
+
+ String widgetset = application.getWidgetsetForRoot(root);
+ if (widgetset == null) {
+ widgetset = getApplicationOrSystemProperty(request,
+ AbstractApplicationServlet.PARAMETER_WIDGETSET,
+ AbstractApplicationServlet.DEFAULT_WIDGETSET);
+ }
+ String widgetsetBasePath = request.getStaticFileLocation();
+
+ widgetset = AbstractApplicationServlet.stripSpecialChars(widgetset);
+
+ final String widgetsetFilePath = widgetsetBasePath + "/"
+ + AbstractApplicationServlet.WIDGETSET_DIRECTORY_PATH
+ + widgetset + "/" + widgetset + ".nocache.js?"
+ + System.currentTimeMillis();
+
+ // Get system messages
+ Application.SystemMessages systemMessages = AbstractApplicationServlet
+ .getSystemMessages(application.getClass());
+
+ page.write("<script type=\"text/javascript\">\n");
+ page.write("//<![CDATA[\n");
+ page.write("if(!vaadin || !vaadin.vaadinConfigurations) {\n "
+ + "if(!vaadin) { var vaadin = {}} \n"
+ + "vaadin.vaadinConfigurations = {};\n"
+ + "if (!vaadin.themesLoaded) { vaadin.themesLoaded = {}; }\n");
+ if (!application.isProductionMode()) {
+ page.write("vaadin.debug = true;\n");
+ }
+ 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");
+ page.write("document.write(\"<script language='javascript' src='"
+ + widgetsetFilePath + "'><\\/script>\");\n}\n");
+
+ page.write("vaadin.vaadinConfigurations[\"" + appId + "\"] = {");
+ page.write("appUri:'" + appUrl + "', ");
+
+ page.write(ApplicationConnection.ROOT_ID_PARAMETER + ": "
+ + root.getRootId() + ", ");
+
+ if (isStandalone()) {
+ page.write("standalone: true, ");
+ }
+ page.write("themeUri:");
+ page.write(themeUri != null ? "\"" + themeUri + "\"" : "null");
+ page.write(", versionInfo : {vaadinVersion:\"");
+ page.write(AbstractApplicationServlet.VERSION);
+ page.write("\",applicationVersion:\"");
+ page.write(JsonPaintTarget.escapeJSON(application.getVersion()));
+ page.write("\"}");
+ if (systemMessages != null) {
+ // Write the CommunicationError -message to client
+ String caption = systemMessages.getCommunicationErrorCaption();
+ if (caption != null) {
+ caption = "\"" + JsonPaintTarget.escapeJSON(caption) + "\"";
+ }
+ String message = systemMessages.getCommunicationErrorMessage();
+ if (message != null) {
+ message = "\"" + JsonPaintTarget.escapeJSON(message) + "\"";
+ }
+ String url = systemMessages.getCommunicationErrorURL();
+ if (url != null) {
+ url = "\"" + JsonPaintTarget.escapeJSON(url) + "\"";
+ }
+
+ page.write(",\"comErrMsg\": {" + "\"caption\":" + caption + ","
+ + "\"message\" : " + message + "," + "\"url\" : " + url
+ + "}");
+
+ // Write the AuthenticationError -message to client
+ caption = systemMessages.getAuthenticationErrorCaption();
+ if (caption != null) {
+ caption = "\"" + JsonPaintTarget.escapeJSON(caption) + "\"";
+ }
+ message = systemMessages.getAuthenticationErrorMessage();
+ if (message != null) {
+ message = "\"" + JsonPaintTarget.escapeJSON(message) + "\"";
+ }
+ url = systemMessages.getAuthenticationErrorURL();
+ if (url != null) {
+ url = "\"" + JsonPaintTarget.escapeJSON(url) + "\"";
+ }
+
+ page.write(",\"authErrMsg\": {" + "\"caption\":" + caption + ","
+ + "\"message\" : " + message + "," + "\"url\" : " + url
+ + "}");
+ }
+ page.write("};\n//]]>\n</script>\n");
+
+ if (themeName != null) {
+ // Custom theme's stylesheet, load only once, in different
+ // script
+ // tag to be dominate styles injected by widget
+ // set
+ page.write("<script type=\"text/javascript\">\n");
+ page.write("//<![CDATA[\n");
+ page.write("if(!vaadin.themesLoaded['" + themeName + "']) {\n");
+ page.write("var stylesheet = document.createElement('link');\n");
+ page.write("stylesheet.setAttribute('rel', 'stylesheet');\n");
+ page.write("stylesheet.setAttribute('type', 'text/css');\n");
+ page.write("stylesheet.setAttribute('href', '" + themeUri
+ + "/styles.css');\n");
+ page.write("document.getElementsByTagName('head')[0].appendChild(stylesheet);\n");
+ page.write("vaadin.themesLoaded['" + themeName + "'] = true;\n}\n");
+ page.write("//]]>\n</script>\n");
+ }
+
+ // Warn if the widgetset has not been loaded after 15 seconds on
+ // inactivity
+ page.write("<script type=\"text/javascript\">\n");
+ page.write("//<![CDATA[\n");
+ page.write("setTimeout('if (typeof " + widgetset.replace('.', '_')
+ + " == \"undefined\") {alert(\"Failed to load the widgetset: "
+ + widgetsetFilePath + "\")};',15000);\n" + "//]]>\n</script>\n");
+ }
+
+ protected abstract String getApplicationOrSystemProperty(
+ WrappedRequest request, String parameter, String defaultValue);
+
+ /**
+ * @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;
+ }
+
+ /**
+ * 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)
+ throws IOException {
+ 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
+ // installed)
+ page.write("<meta http-equiv=\"X-UA-Compatible\" content=\"chrome=1\"/>\n");
+
+ page.write("<style type=\"text/css\">"
+ + "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\" />");
+
+ page.write("<title>"
+ + AbstractApplicationServlet.safeEscapeForHtml(title)
+ + "</title>");
+ }
+
+ /**
+ * Method to set http request headers for the Vaadin kickstart page.
+ * <p>
+ * Override this method if you need to customize http headers of the page.
+ *
+ * @param response
+ */
+ protected void setAjaxPageHeaders(WrappedResponse response) {
+ // Window renders are not cacheable
+ response.setHeader("Cache-Control", "no-cache");
+ response.setHeader("Pragma", "no-cache");
+ response.setDateHeader("Expires", 0);
+ response.setContentType("text/html; charset=UTF-8");
+ }
+
+ /**
+ * Method to write the beginning of the html page.
+ * <p>
+ * This method is responsible for writing appropriate doc type declarations
+ * and to open html and head tags.
+ * <p>
+ * Override this method if you want to add some custom html to the very
+ * beginning of the page.
+ *
+ * @param page
+ * @param request
+ * @throws IOException
+ */
+ protected void writeAjaxPageHtmlHeadStart(final BufferedWriter page,
+ final WrappedRequest request) throws IOException {
+ // write html header
+ page.write("<!DOCTYPE html PUBLIC \"-//W3C//DTD "
+ + "XHTML 1.0 Transitional//EN\" "
+ + "\"http://www.w3.org/TR/xhtml1/"
+ + "DTD/xhtml1-transitional.dtd\">\n");
+
+ page.write("<html xmlns=\"http://www.w3.org/1999/xhtml\""
+ + ">\n<head>\n");
+ }
+
+ /**
+ * Get the URI for the application theme.
+ *
+ * A portal-wide default theme is fetched from the portal shared resource
+ * directory (if any), other themes from the portlet.
+ *
+ * @param themeName
+ * @param request
+ * @return
+ */
+ private String getThemeUri(String themeName, WrappedRequest request) {
+ final String staticFilePath = request.getStaticFileLocation();
+ return staticFilePath + "/"
+ + AbstractApplicationServlet.THEME_DIRECTORY_PATH + themeName;
+ }
+
+ /**
+ * Returns the theme for given request/root
+ *
+ * @param request
+ * @param root
+ * @return
+ */
+ private String getThemeForRoot(WrappedRequest request, Root root) {
+ // 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);
+ }
+
+ if (themeName == null) {
+ // no explicit theme for root defined
+ // using the default theme defined by Vaadin
+ themeName = AbstractApplicationServlet.getDefaultTheme();
+ }
+
+ // XSS preventation, theme names shouldn't contain special chars anyway.
+ // The servlet denies them via url parameter.
+ themeName = AbstractApplicationServlet.stripSpecialChars(themeName);
+
+ return themeName;
+ }
protected void writeError(WrappedResponse response, Throwable e)
throws IOException {
diff --git a/src/com/vaadin/terminal/gwt/server/WrappedHttpServletRequest.java b/src/com/vaadin/terminal/gwt/server/WrappedHttpServletRequest.java
index 1ce97b10ba..4d947d20b0 100644
--- a/src/com/vaadin/terminal/gwt/server/WrappedHttpServletRequest.java
+++ b/src/com/vaadin/terminal/gwt/server/WrappedHttpServletRequest.java
@@ -91,4 +91,8 @@ public class WrappedHttpServletRequest implements WrappedRequest {
public AbstractApplicationServlet getServlet() {
return servlet;
}
+
+ public String getStaticFileLocation() {
+ return servlet.getStaticFilesLocation(request);
+ }
} \ No newline at end of file
diff --git a/src/com/vaadin/terminal/gwt/server/WrappedPortletRequest.java b/src/com/vaadin/terminal/gwt/server/WrappedPortletRequest.java
index 608f7ee63b..e8e7350d42 100644
--- a/src/com/vaadin/terminal/gwt/server/WrappedPortletRequest.java
+++ b/src/com/vaadin/terminal/gwt/server/WrappedPortletRequest.java
@@ -104,4 +104,8 @@ public class WrappedPortletRequest implements WrappedRequest {
return ((ResourceRequest) request).getContentType();
}
+ public String getStaticFileLocation() {
+ throw new UnsupportedOperationException("Please implement me!");
+ }
+
} \ No newline at end of file