From: Henri Sara Date: Thu, 18 Feb 2010 08:04:08 +0000 (+0000) Subject: Refactoring of AbstractApplicationPortlet for (limited) extensibility of request... X-Git-Tag: 6.7.0.beta1~2043 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=cf86862c2c9e15ae908ad4152a01693e1e19e4b7;p=vaadin-framework.git Refactoring of AbstractApplicationPortlet for (limited) extensibility of request processing and HTML/javascript generation. svn changeset:11366/svn branch:6.3 --- diff --git a/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java b/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java index 680cf0709a..708177e858 100644 --- a/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java +++ b/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java @@ -14,6 +14,7 @@ import java.security.GeneralSecurityException; import java.util.Date; import java.util.Enumeration; import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.Locale; import java.util.Map; import java.util.Properties; @@ -45,9 +46,14 @@ import com.vaadin.Application.SystemMessages; import com.vaadin.external.org.apache.commons.fileupload.portlet.PortletFileUpload; import com.vaadin.terminal.DownloadStream; import com.vaadin.terminal.Terminal; +import com.vaadin.terminal.gwt.client.ApplicationConfiguration; +import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.ui.Window; /** + * Portlet 2.0 base class. This replaces the servlet in servlet/portlet 1.0 + * deployments and handles various portlet requests from the browser. + * * TODO Document me! * * @author peholmst @@ -191,7 +197,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet * the Default to be used. * @return String value or default if not found */ - private String getApplicationOrSystemProperty(String parameterName, + protected String getApplicationOrSystemProperty(String parameterName, String defaultValue) { String val = null; @@ -238,7 +244,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet } } - enum RequestType { + protected enum RequestType { FILE_UPLOAD, UIDL, RENDER, STATIC_FILE, APPLICATION_RESOURCE, DUMMY, EVENT, ACTION, UNKNOWN; } @@ -302,7 +308,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet RequestType requestType = getRequestType(request); if (requestType == RequestType.UNKNOWN) { - System.err.println("Unknown request type"); + handleUnknownRequest(request, response); } else if (requestType == RequestType.DUMMY) { /* * This dummy page is used by action responses to redirect to, in @@ -421,45 +427,8 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet return; } - /* - * Always use the main window when running inside a portlet. - */ - Window window = application.getMainWindow(); - if (window == null) { - throw new PortletException(ERROR_NO_WINDOW_FOUND); - } - - /* - * Sets terminal type for the window, if not already set - */ - if (window.getTerminal() == null) { - window.setTerminal(applicationContext.getBrowser()); - } - - /* - * Handle parameters - */ - final Map parameters = request - .getParameterMap(); - if (window != null && parameters != null) { - window.handleParameters(parameters); - } - - if (requestType == RequestType.APPLICATION_RESOURCE) { - handleURI(applicationManager, window, - (ResourceRequest) request, - (ResourceResponse) response); - } else if (requestType == RequestType.RENDER) { - writeAjaxPage((RenderRequest) request, - (RenderResponse) response, window, application); - } else if (requestType == RequestType.EVENT) { - // nothing to do, listeners do all the work - } else if (requestType == RequestType.ACTION) { - // nothing to do, listeners do all the work - } else { - throw new IllegalStateException( - "handleRequest() without anything to do - should never happen!"); - } + handleOtherRequest(request, response, requestType, + application, applicationContext, applicationManager); } } catch (final SessionExpiredException e) { // TODO Figure out a better way to deal with @@ -492,6 +461,73 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet } } + protected void handleUnknownRequest(PortletRequest request, + PortletResponse response) { + System.err.println("Unknown request type"); + } + + /** + * Handle a portlet request that is not for static files, UIDL or upload. + * Also render requests are handled here. + * + * This method is called after starting the application and calling portlet + * and transaction listeners. + * + * @param request + * @param response + * @param requestType + * @param application + * @param applicationContext + * @param applicationManager + * @throws PortletException + * @throws IOException + * @throws MalformedURLException + */ + protected void handleOtherRequest(PortletRequest request, + PortletResponse response, RequestType requestType, + Application application, + PortletApplicationContext2 applicationContext, + PortletCommunicationManager applicationManager) + throws PortletException, IOException, MalformedURLException { + /* + * Always use the main window when running inside a portlet. + */ + Window window = application.getMainWindow(); + if (window == null) { + throw new PortletException(ERROR_NO_WINDOW_FOUND); + } + + /* + * Sets terminal type for the window, if not already set + */ + if (window.getTerminal() == null) { + window.setTerminal(applicationContext.getBrowser()); + } + + /* + * Handle parameters + */ + final Map parameters = request.getParameterMap(); + if (window != null && parameters != null) { + window.handleParameters(parameters); + } + + if (requestType == RequestType.APPLICATION_RESOURCE) { + handleURI(applicationManager, window, (ResourceRequest) request, + (ResourceResponse) response); + } else if (requestType == RequestType.RENDER) { + writeAjaxPage((RenderRequest) request, (RenderResponse) response, + window, application); + } else if (requestType == RequestType.EVENT) { + // nothing to do, listeners do all the work + } else if (requestType == RequestType.ACTION) { + // nothing to do, listeners do all the work + } else { + throw new IllegalStateException( + "handleRequest() without anything to do - should never happen!"); + } + } + private void updateBrowserProperties(WebBrowser browser, PortletRequest request) { browser.updateBrowserProperties(request.getLocale(), null, request @@ -505,7 +541,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet handleRequest(request, response); } - private boolean handleURI(PortletCommunicationManager applicationManager, + protected boolean handleURI(PortletCommunicationManager applicationManager, Window window, ResourceRequest request, ResourceResponse response) throws IOException { // Handles the URI @@ -523,8 +559,9 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet } @SuppressWarnings("unchecked") - private void handleDownload(DownloadStream stream, ResourceRequest request, - ResourceResponse response) throws IOException { + protected void handleDownload(DownloadStream stream, + ResourceRequest request, ResourceResponse response) + throws IOException { if (stream.getParameter("Location") != null) { response.setProperty(ResourceResponse.HTTP_STATUS_CODE, Integer @@ -782,17 +819,63 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet return null; } + /** + * Returns the URL from which the widgetset is served on the portal. + * + * @param widgetset + * @param request + * @return + */ protected String getWidgetsetURL(String widgetset, PortletRequest request) { return getStaticFilesLocation(request) + "/" + WIDGETSET_DIRECTORY_PATH + widgetset + "/" + widgetset + ".nocache.js?" + new Date().getTime(); } + /** + * Returns the theme URI for the named theme on the portal. + * + * Note that this is not the only location referring to the theme URI - also + * e.g. PortletCommunicationManager uses its own way to access the portlet + * 2.0 theme resources. + * + * @param themeName + * @param request + * @return + */ protected String getThemeURI(String themeName, PortletRequest request) { return getStaticFilesLocation(request) + "/" + THEME_DIRECTORY_PATH + themeName; } + /** + * Writes the html host page (aka kickstart page) that starts the actual + * Vaadin application. + * + * If one needs to override parts of the portlet HTML contents creation, it + * is suggested that one overrides one of several submethods including: + *
    + *
  • + * {@link #writeAjaxPageHtmlMainDiv(RenderRequest, RenderResponse, BufferedWriter, String)} + *
  • + * {@link #getVaadinConfigurationMap(RenderRequest, RenderResponse, Application, String)} + *
  • + * {@link #writeAjaxPageHtmlVaadinScripts(RenderRequest, RenderResponse, BufferedWriter, Application, String)} + *
+ * + * @param request + * the portlet request. + * @param response + * the portlet response to write to. + * @param window + * @param application + * @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. + * @throws PortletException + */ protected void writeAjaxPage(RenderRequest request, RenderResponse response, Window window, Application application) throws IOException, MalformedURLException, PortletException { @@ -801,27 +884,62 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet final BufferedWriter page = new BufferedWriter(new OutputStreamWriter( response.getPortletOutputStream(), "UTF-8")); - // TODO check - String requestWidgetset = getApplicationOrSystemProperty( - PARAMETER_WIDGETSET, null); - String sharedWidgetset = getPortalProperty( - PORTAL_PARAMETER_VAADIN_WIDGETSET, request.getPortalContext()); - - String widgetset; - if (requestWidgetset != null) { - widgetset = requestWidgetset; - } else if (sharedWidgetset != null) { - widgetset = sharedWidgetset; - } else { - widgetset = DEFAULT_WIDGETSET; - } - // TODO Currently, we can only load widgetsets and themes from the // portal String themeName = getThemeForWindow(request, window); - String widgetsetURL = getWidgetsetURL(widgetset, request); + writeAjaxPageHtmlVaadinScripts(request, response, page, application, + themeName); + + /*- Add classnames; + * .v-app + * .v-app-loading + * .v-app- + * .v-theme- + */ + String appClass = "v-app-"; + try { + appClass += getApplicationClass().getSimpleName(); + } catch (ClassNotFoundException e) { + appClass += "unknown"; + e.printStackTrace(); + } + String themeClass = "v-theme-" + + themeName.replaceAll("[^a-zA-Z0-9]", ""); + + String classNames = "v-app v-app-loading " + themeClass + " " + + appClass; + + String style = getApplicationProperty(PORTLET_PARAMETER_STYLE); + String divStyle = ""; + if (style != null) { + divStyle = "style=\"" + style + "\""; + } + + writeAjaxPageHtmlMainDiv(request, response, page, + request.getWindowID(), classNames, divStyle); + + page.close(); + } + + /** + * This method writes the scripts to load the widgetset and the themes as + * well as define Vaadin configuration parameters on the HTML fragment that + * starts the actual Vaadin application. + * + * @param request + * @param response + * @param writer + * @param application + * @param themeName + * @throws IOException + * @throws PortletException + */ + protected void writeAjaxPageHtmlVaadinScripts(RenderRequest request, + RenderResponse response, final BufferedWriter writer, + Application application, String themeName) throws IOException, + PortletException { String themeURI = getThemeURI(themeName, request); // fixed base theme to use - all portal pages with Vaadin @@ -829,52 +947,113 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet String portalTheme = getPortalProperty(PORTAL_PARAMETER_VAADIN_THEME, request.getPortalContext()); - // 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 PortletException("Failed to obtain system messages!", e); - } - - page.write("\n"); + + writeAjaxPageHtmlTheme(request, writer, themeName, themeURI, + portalTheme); + + // TODO Warn if widgetset has not been loaded after 15 seconds + } + + /** + * Writes the script to load the widgetset on the HTML fragment created by + * the portlet. + * + * @param request + * @param response + * @param writer + * @throws IOException + */ + protected void writeAjaxPageScriptWidgetset(RenderRequest request, + RenderResponse response, final BufferedWriter writer) + throws IOException { + String requestWidgetset = getApplicationOrSystemProperty( + PARAMETER_WIDGETSET, null); + String sharedWidgetset = getPortalProperty( + PORTAL_PARAMETER_VAADIN_WIDGETSET, request.getPortalContext()); + + String widgetset; + if (requestWidgetset != null) { + widgetset = requestWidgetset; + } else if (sharedWidgetset != null) { + widgetset = sharedWidgetset; + } else { + widgetset = DEFAULT_WIDGETSET; + } + String widgetsetURL = getWidgetsetURL(widgetset, request); + writer .write("document.write('');\n"); - page.write("document.write(\"\n"); - page.write("\n"); - - // TODO Warn if widgetset has not been loaded after 15 seconds - - /*- Add classnames; - * .v-app - * .v-app-loading - * .v-app- - * .v-theme- - */ - - String appClass = "v-app-"; - try { - appClass += getApplicationClass().getSimpleName(); - } catch (ClassNotFoundException e) { - appClass += "unknown"; - e.printStackTrace(); + writer.write("vaadin.themesLoaded['" + themeName + + "'] = true;\n}\n"); } - String themeClass = "v-theme-" - + themeName.replaceAll("[^a-zA-Z0-9]", ""); - String classNames = "v-app v-app-loading " + themeClass + " " - + appClass; + writer.write("\n"); + } - String style = getApplicationProperty(PORTLET_PARAMETER_STYLE); - String divStyle = ""; - if (style != null) { - divStyle = "style=\"" + style + "\""; - } - page.write("
+ * 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 request + * @param response + * @param writer + * @param id + * @param classNames + * @param divStyle + * @throws IOException + */ + protected void writeAjaxPageHtmlMainDiv(RenderRequest request, + RenderResponse response, final BufferedWriter writer, String id, + String classNames, String divStyle) throws IOException { + writer.write("
\n"); - - page.close(); } /** @@ -966,7 +1189,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet * @param window * @return */ - private String getThemeForWindow(PortletRequest request, Window window) { + protected String getThemeForWindow(PortletRequest request, Window window) { // Finds theme name String themeName; @@ -1143,7 +1366,18 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet out.flush(); } - private static String getPortalProperty(String name, PortalContext context) { + /** + * Returns a portal configuration property. + * + * Liferay is handled separately as + * {@link PortalContext#getProperty(String)} does not return portal + * properties from e.g. portal-ext.properties . + * + * @param name + * @param context + * @return + */ + protected static String getPortalProperty(String name, PortalContext context) { boolean isLifeRay = context.getPortalInfo().toLowerCase().contains( "liferay"); diff --git a/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java b/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java index 7a3978f323..f2725055a4 100644 --- a/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java +++ b/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java @@ -1489,7 +1489,7 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements * 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 + * the div element into which the actual Vaadin application will be * rendered. * * @param page @@ -1507,8 +1507,7 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements } /** - * - * * Method to write the script part of the page which loads needed vaadin + * 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.