From dc80599cb99066b8fb8135f580efa631f28f13d2 Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Tue, 22 Nov 2011 17:40:51 +0200 Subject: Move ajax page generation code to AjaxPageHandler --- src/com/vaadin/Application.java | 5 + src/com/vaadin/terminal/WrappedRequest.java | 2 + .../gwt/server/AbstractApplicationServlet.java | 468 +-------------------- .../gwt/server/AbstractCommunicationManager.java | 23 +- .../terminal/gwt/server/AjaxPageHandler.java | 411 +++++++++++++++++- .../gwt/server/WrappedHttpServletRequest.java | 4 + .../terminal/gwt/server/WrappedPortletRequest.java | 4 + 7 files changed, 447 insertions(+), 470 deletions(-) (limited to 'src') 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( 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; @@ -853,36 +852,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 @@ -1344,13 +1313,25 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements * @return */ protected SystemMessages getSystemMessages() { + Class appCls = null; try { - Class 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 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); @@ -1467,421 +1448,6 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements response.sendRedirect(response.encodeRedirectURL(applicationUrl)); } - /** - * This method writes the html host page (aka kickstart page) that starts - * the actual Vaadin application. - *

- * 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: - *

- * - * @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- - * .v-theme- - */ - - 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("\n\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. - *

- * 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("

"); - page.write("
"); - page.write("
\n"); - page.write(""); - } - - /** - * Method to write the script part of the page which loads needed Vaadin - * scripts and themes. - *

- * 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("\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("\n"); - } - - // Warn if the widgetset has not been loaded after 15 seconds on - // inactivity - page.write("\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. - *

- * This method is responsible for closing the head tag and opening the body - * tag. - *

- * 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\n\n"); - } - - /** - * Method to write the contents of head element in html kickstart page. - *

- * 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("\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("\n"); - } - - page.write(""); - - // Add favicon links - page.write(""); - page.write(""); - - page.write("" + safeEscapeForHtml(title) + ""); - } - - /** - * Method to write the beginning of the html page. - *

- * This method is responsible for writing appropriate doc type declarations - * and to open html and head tags. - *

- * 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("\n"); - - page.write("\n\n"); - } - - /** - * Method to set http request headers for the Vaadin kickstart page. - *

- * 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. * 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- + * .v-theme- + */ + + 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("\n\n"); + + page.close(); + } + + /** + * Method to write the div element into which that actual Vaadin application + * is rendered. + *

+ * 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("

"); + page.write("
"); + page.write("
\n"); + page.write(""); + } + + /** + * 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. + *

+ * This method is responsible for closing the head tag and opening the body + * tag. + *

+ * 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\n\n"); + } + + /** + * Method to write the script part of the page which loads needed Vaadin + * scripts and themes. + *

+ * 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("\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("\n"); + } + + // Warn if the widgetset has not been loaded after 15 seconds on + // inactivity + page.write("\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. + *

+ * 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("\n"); + + // Chrome frame in all versions of IE (only if Chrome frame is + // installed) + page.write("\n"); + + page.write(""); + + // Add favicon links + page.write(""); + page.write(""); + + page.write("" + + AbstractApplicationServlet.safeEscapeForHtml(title) + + ""); + } + + /** + * Method to set http request headers for the Vaadin kickstart page. + *

+ * 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. + *

+ * This method is responsible for writing appropriate doc type declarations + * and to open html and head tags. + *

+ * 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("\n"); + + page.write("\n\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 -- cgit v1.2.3