aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLeif Åstrand <leif@vaadin.com>2011-11-02 14:47:50 +0200
committerLeif Åstrand <leif@vaadin.com>2011-11-02 14:47:50 +0200
commitd9ac7b1ecd571b7ad9a9ae7354207e50fea3754d (patch)
treecdff187aa2994a09102aa0f1001b390028183ae7 /src
parent432a764e515873f1eb6768a6eb9b15f5fc43ce14 (diff)
downloadvaadin-framework-d9ac7b1ecd571b7ad9a9ae7354207e50fea3754d.tar.gz
vaadin-framework-d9ac7b1ecd571b7ad9a9ae7354207e50fea3754d.zip
Restored (completely untested) support for portlets using Root
Diffstat (limited to 'src')
-rw-r--r--src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java3244
-rw-r--r--src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java2
-rw-r--r--src/com/vaadin/terminal/gwt/server/ApplicationPortlet.java494
-rw-r--r--src/com/vaadin/terminal/gwt/server/ApplicationPortlet2.java86
-rw-r--r--src/com/vaadin/terminal/gwt/server/CommunicationManager.java9
-rw-r--r--src/com/vaadin/terminal/gwt/server/PortletApplicationContext2.java834
-rw-r--r--src/com/vaadin/terminal/gwt/server/PortletCommunicationManager.java603
7 files changed, 2637 insertions, 2635 deletions
diff --git a/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java b/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java
index a0a0abb476..e0dc7a0d26 100644
--- a/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java
+++ b/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java
@@ -1,1625 +1,1625 @@
/*
@ITMillApache2LicenseForJavaFiles@
*/
-//package com.vaadin.terminal.gwt.server;
-//
-//import java.io.BufferedWriter;
-//import java.io.IOException;
-//import java.io.InputStream;
-//import java.io.OutputStream;
-//import java.io.OutputStreamWriter;
-//import java.io.PrintWriter;
-//import java.io.Serializable;
-//import java.lang.reflect.InvocationTargetException;
-//import java.lang.reflect.Method;
-//import java.net.MalformedURLException;
-//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;
-//import java.util.logging.Level;
-//import java.util.logging.Logger;
-//
-//import javax.portlet.ActionRequest;
-//import javax.portlet.ActionResponse;
-//import javax.portlet.EventRequest;
-//import javax.portlet.EventResponse;
-//import javax.portlet.GenericPortlet;
-//import javax.portlet.MimeResponse;
-//import javax.portlet.PortalContext;
-//import javax.portlet.PortletConfig;
-//import javax.portlet.PortletContext;
-//import javax.portlet.PortletException;
-//import javax.portlet.PortletRequest;
-//import javax.portlet.PortletResponse;
-//import javax.portlet.PortletSession;
-//import javax.portlet.PortletURL;
-//import javax.portlet.RenderRequest;
-//import javax.portlet.RenderResponse;
-//import javax.portlet.ResourceRequest;
-//import javax.portlet.ResourceResponse;
-//import javax.portlet.ResourceURL;
-//import javax.servlet.http.HttpServletRequest;
-//import javax.servlet.http.HttpServletRequestWrapper;
-//import javax.servlet.http.HttpServletResponse;
-//
-//import com.liferay.portal.kernel.util.PortalClassInvoker;
-//import com.liferay.portal.kernel.util.PropsUtil;
-//import com.vaadin.Application;
-//import com.vaadin.Application.SystemMessages;
-//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
-// */
-//public abstract class AbstractApplicationPortlet extends GenericPortlet
-// implements Constants {
-//
-// private static final Logger logger = Logger
-// .getLogger(AbstractApplicationPortlet.class.getName());
-//
-// /**
-// * This portlet parameter is used to add styles to the main element. E.g
-// * "height:500px" generates a style="height:500px" to the main element.
-// */
-// public static final String PORTLET_PARAMETER_STYLE = "style";
-//
-// private static final String PORTAL_PARAMETER_VAADIN_THEME = "vaadin.theme";
-//
-// // TODO some parts could be shared with AbstractApplicationServlet
-//
-// // TODO Can we close the application when the portlet is removed? Do we know
-// // when the portlet is removed?
-//
-// // TODO What happens when the portlet window is resized? Do we know when the
-// // window is resized?
-//
-// private Properties applicationProperties;
-//
-// private boolean productionMode = false;
-//
-// @Override
-// public void init(PortletConfig config) throws PortletException {
-// super.init(config);
-// // Stores the application parameters into Properties object
-// applicationProperties = new Properties();
-// for (final Enumeration<String> e = config.getInitParameterNames(); e
-// .hasMoreElements();) {
-// final String name = e.nextElement();
-// applicationProperties.setProperty(name,
-// config.getInitParameter(name));
-// }
-//
-// // Overrides with server.xml parameters
-// final PortletContext context = config.getPortletContext();
-// for (final Enumeration<String> e = context.getInitParameterNames(); e
-// .hasMoreElements();) {
-// final String name = e.nextElement();
-// applicationProperties.setProperty(name,
-// context.getInitParameter(name));
-// }
-// checkProductionMode();
-// checkCrossSiteProtection();
-// }
-//
-// private void checkCrossSiteProtection() {
-// if (getApplicationOrSystemProperty(
-// SERVLET_PARAMETER_DISABLE_XSRF_PROTECTION, "false").equals(
-// "true")) {
-// /*
-// * Print an information/warning message about running with xsrf
-// * protection disabled
-// */
-// logger.warning(WARNING_XSRF_PROTECTION_DISABLED);
-// }
-// }
-//
-// /**
-// * Checks that the version reported by the client (widgetset) matches that
-// * of the server.
-// *
-// * @param request
-// */
-// private void checkWidgetsetVersion(PortletRequest request) {
-// if (!AbstractApplicationServlet.VERSION.equals(getHTTPRequestParameter(
-// request, "wsver"))) {
-// logger.warning(String.format(WIDGETSET_MISMATCH_INFO,
-// AbstractApplicationServlet.VERSION,
-// getHTTPRequestParameter(request, "wsver")));
-// }
-// }
-//
-// private void checkProductionMode() {
-// // Check if the application is in production mode.
-// // We are in production mode if Debug=false or productionMode=true
-// if (getApplicationOrSystemProperty(SERVLET_PARAMETER_DEBUG, "true")
-// .equals("false")) {
-// // "Debug=true" is the old way and should no longer be used
-// productionMode = true;
-// } else if (getApplicationOrSystemProperty(
-// SERVLET_PARAMETER_PRODUCTION_MODE, "false").equals("true")) {
-// // "productionMode=true" is the real way to do it
-// productionMode = true;
-// }
-//
-// if (!productionMode) {
-// /* Print an information/warning message about running in debug mode */
-// // TODO Maybe we need a different message for portlets?
-// logger.warning(NOT_PRODUCTION_MODE_INFO);
-// }
-// }
-//
-// /**
-// * Gets an application property value.
-// *
-// * @param parameterName
-// * the Name or the parameter.
-// * @return String value or null if not found
-// */
-// protected String getApplicationProperty(String parameterName) {
-//
-// String val = applicationProperties.getProperty(parameterName);
-// if (val != null) {
-// return val;
-// }
-//
-// // Try lower case application properties for backward compatibility with
-// // 3.0.2 and earlier
-// val = applicationProperties.getProperty(parameterName.toLowerCase());
-//
-// return val;
-// }
-//
-// /**
-// * Gets an system property value.
-// *
-// * @param parameterName
-// * the Name or the parameter.
-// * @return String value or null if not found
-// */
-// protected String getSystemProperty(String parameterName) {
-// String val = null;
-//
-// String pkgName;
-// final Package pkg = getClass().getPackage();
-// if (pkg != null) {
-// pkgName = pkg.getName();
-// } else {
-// final String className = getClass().getName();
-// pkgName = new String(className.toCharArray(), 0,
-// className.lastIndexOf('.'));
-// }
-// val = System.getProperty(pkgName + "." + parameterName);
-// if (val != null) {
-// return val;
-// }
-//
-// // Try lowercased system properties
-// val = System.getProperty(pkgName + "." + parameterName.toLowerCase());
-// return val;
-// }
-//
-// /**
-// * Gets an application or system property value.
-// *
-// * @param parameterName
-// * the Name or the parameter.
-// * @param defaultValue
-// * the Default to be used.
-// * @return String value or default if not found
-// */
-// protected String getApplicationOrSystemProperty(String parameterName,
-// String defaultValue) {
-//
-// String val = null;
-//
-// // Try application properties
-// val = getApplicationProperty(parameterName);
-// if (val != null) {
-// return val;
-// }
-//
-// // Try system properties
-// val = getSystemProperty(parameterName);
-// if (val != null) {
-// return val;
-// }
-//
-// return defaultValue;
-// }
-//
-// /**
-// * Return the URL from where static files, e.g. the widgetset and the theme,
-// * are served. In a standard configuration the VAADIN folder inside the
-// * returned folder is what is used for widgetsets and themes.
-// *
-// * @param request
-// * @return The location of static resources (inside which there should be a
-// * VAADIN directory). Does not end with a slash (/).
-// */
-// protected String getStaticFilesLocation(PortletRequest request) {
-// // TODO allow overriding on portlet level?
-// String staticFileLocation = getPortalProperty(
-// Constants.PORTAL_PARAMETER_VAADIN_RESOURCE_PATH,
-// request.getPortalContext());
-// if (staticFileLocation != null) {
-// // remove trailing slash if any
-// while (staticFileLocation.endsWith(".")) {
-// staticFileLocation = staticFileLocation.substring(0,
-// staticFileLocation.length() - 1);
-// }
-// return staticFileLocation;
-// } else {
-// // default for Liferay
-// return "/html";
-// }
-// }
-//
-// protected enum RequestType {
-// FILE_UPLOAD, UIDL, RENDER, STATIC_FILE, APPLICATION_RESOURCE, DUMMY, EVENT, ACTION, UNKNOWN;
-// }
-//
-// protected RequestType getRequestType(PortletRequest request) {
-// if (request instanceof RenderRequest) {
-// return RequestType.RENDER;
-// } else if (request instanceof ResourceRequest) {
-// if (isUIDLRequest((ResourceRequest) request)) {
-// return RequestType.UIDL;
-// } else if (isFileUploadRequest((ResourceRequest) request)) {
-// return RequestType.FILE_UPLOAD;
-// } else if (isApplicationResourceRequest((ResourceRequest) request)) {
-// return RequestType.APPLICATION_RESOURCE;
-// } else if (isDummyRequest((ResourceRequest) request)) {
-// return RequestType.DUMMY;
-// } else {
-// return RequestType.STATIC_FILE;
-// }
-// } else if (request instanceof ActionRequest) {
-// return RequestType.ACTION;
-// } else if (request instanceof EventRequest) {
-// return RequestType.EVENT;
-// }
-// return RequestType.UNKNOWN;
-// }
-//
-// private boolean isApplicationResourceRequest(ResourceRequest request) {
-// return request.getResourceID() != null
-// && request.getResourceID().startsWith("APP");
-// }
-//
-// private boolean isUIDLRequest(ResourceRequest request) {
-// return request.getResourceID() != null
-// && request.getResourceID().equals("UIDL");
-// }
-//
-// private boolean isDummyRequest(ResourceRequest request) {
-// return request.getResourceID() != null
-// && request.getResourceID().equals("DUMMY");
-// }
-//
-// private boolean isFileUploadRequest(ResourceRequest request) {
-// return "UPLOAD".equals(request.getResourceID());
-// }
-//
-// /**
-// * Returns true if the servlet is running in production mode. Production
-// * mode disables all debug facilities.
-// *
-// * @return true if in production mode, false if in debug mode
-// */
-// public boolean isProductionMode() {
-// return productionMode;
-// }
-//
-// protected void handleRequest(PortletRequest request,
-// PortletResponse response) throws PortletException, IOException {
-// RequestType requestType = getRequestType(request);
-//
-// if (requestType == RequestType.UNKNOWN) {
-// handleUnknownRequest(request, response);
-// } else if (requestType == RequestType.DUMMY) {
-// /*
-// * This dummy page is used by action responses to redirect to, in
-// * order to prevent the boot strap code from being rendered into
-// * strange places such as iframes.
-// */
-// ((ResourceResponse) response).setContentType("text/html");
-// final OutputStream out = ((ResourceResponse) response)
-// .getPortletOutputStream();
-// final PrintWriter outWriter = new PrintWriter(new BufferedWriter(
-// new OutputStreamWriter(out, "UTF-8")));
-// outWriter.print("<html><body>dummy page</body></html>");
-// outWriter.close();
-// } else if (requestType == RequestType.STATIC_FILE) {
-// serveStaticResources((ResourceRequest) request,
-// (ResourceResponse) response);
-// } else {
-// Application application = null;
-// boolean transactionStarted = false;
-// boolean requestStarted = false;
-//
-// try {
-// // TODO What about PARAM_UNLOADBURST & redirectToApplication??
-//
-// /* Find out which application this request is related to */
-// application = findApplicationInstance(request, requestType);
-// if (application == null) {
-// return;
-// }
-//
-// /*
-// * Get or create an application context and an application
-// * manager for the session
-// */
-// PortletApplicationContext2 applicationContext = getApplicationContext(request
-// .getPortletSession());
-// applicationContext.setResponse(response);
-// applicationContext.setPortletConfig(getPortletConfig());
-//
-// PortletCommunicationManager applicationManager = applicationContext
-// .getApplicationManager(application);
-//
-// /* Update browser information from request */
-// updateBrowserProperties(applicationContext.getBrowser(),
-// request);
-//
-// /*
-// * Call application requestStart before Application.init() is
-// * called (bypasses the limitation in TransactionListener)
-// */
-// if (application instanceof PortletRequestListener) {
-// ((PortletRequestListener) application).onRequestStart(
-// request, response);
-// requestStarted = true;
-// }
-//
-// /* Start the newly created application */
-// startApplication(request, application, applicationContext);
-//
-// /*
-// * Transaction starts. Call transaction listeners. Transaction
-// * end is called in the finally block below.
-// */
-// applicationContext.startTransaction(application, request);
-// transactionStarted = true;
-//
-// /* Notify listeners */
-//
-// // Finds the window within the application
-// Window window = null;
-// synchronized (application) {
-// if (application.isRunning()) {
-// switch (requestType) {
-// case FILE_UPLOAD:
-// // no window
-// break;
-// case APPLICATION_RESOURCE:
-// // use main window - should not need any window
-// window = application.getMainWindow();
-// break;
-// default:
-// window = applicationManager.getApplicationWindow(
-// request, this, application, null);
-// }
-// // if window not found, not a problem - use null
-// }
-// }
-//
-// // TODO Should this happen before or after the transaction
-// // starts?
-// if (request instanceof RenderRequest) {
-// applicationContext.firePortletRenderRequest(application,
-// window, (RenderRequest) request,
-// (RenderResponse) response);
-// } else if (request instanceof ActionRequest) {
-// applicationContext.firePortletActionRequest(application,
-// window, (ActionRequest) request,
-// (ActionResponse) response);
-// } else if (request instanceof EventRequest) {
-// applicationContext.firePortletEventRequest(application,
-// window, (EventRequest) request,
-// (EventResponse) response);
-// } else if (request instanceof ResourceRequest) {
-// applicationContext.firePortletResourceRequest(application,
-// window, (ResourceRequest) request,
-// (ResourceResponse) response);
-// }
-//
-// /* Handle the request */
-// if (requestType == RequestType.FILE_UPLOAD) {
-// applicationManager.handleFileUpload(
-// (ResourceRequest) request,
-// (ResourceResponse) response);
-// return;
-// } else if (requestType == RequestType.UIDL) {
-// // Handles AJAX UIDL requests
-// if (isRepaintAll(request)) {
-// // warn if versions do not match
-// checkWidgetsetVersion(request);
-// }
-// applicationManager.handleUidlRequest(
-// (ResourceRequest) request,
-// (ResourceResponse) response, this, window);
-// return;
-// } else {
-// /*
-// * Removes the application if it has stopped
-// */
-// if (!application.isRunning()) {
-// endApplication(request, response, application);
-// return;
-// }
-//
-// handleOtherRequest(request, response, requestType,
-// application, window, applicationContext,
-// applicationManager);
-// }
-// } catch (final SessionExpiredException e) {
-// // TODO Figure out a better way to deal with
-// // SessionExpiredExceptions
-// logger.finest("A user session has expired");
-// } catch (final GeneralSecurityException e) {
-// // TODO Figure out a better way to deal with
-// // GeneralSecurityExceptions
-// logger.fine("General security exception, the security key was probably incorrect.");
-// } catch (final Throwable e) {
-// handleServiceException(request, response, application, e);
-// } finally {
-// // Notifies transaction end
-// try {
-// if (transactionStarted) {
-// ((PortletApplicationContext2) application.getContext())
-// .endTransaction(application, request);
-// }
-// } finally {
-// if (requestStarted) {
-// ((PortletRequestListener) application).onRequestEnd(
-// request, response);
-//
-// }
-// }
-// }
-// }
-// }
-//
-// private void handleUnknownRequest(PortletRequest request,
-// PortletResponse response) {
-// logger.warning("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
-// */
-// private void handleOtherRequest(PortletRequest request,
-// PortletResponse response, RequestType requestType,
-// Application application, Window window,
-// PortletApplicationContext2 applicationContext,
-// PortletCommunicationManager applicationManager)
-// throws PortletException, IOException, MalformedURLException {
-// 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<String, String[]> 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) {
-// String userAgent = getHTTPHeader(request, "user-agent");
-// browser.updateRequestDetails(request.getLocale(), null,
-// request.isSecure(), userAgent);
-// if (getHTTPRequestParameter(request, "repaintAll") != null) {
-// browser.updateClientSideDetails(
-// getHTTPRequestParameter(request, "sw"),
-// getHTTPRequestParameter(request, "sh"),
-// getHTTPRequestParameter(request, "tzo"),
-// getHTTPRequestParameter(request, "rtzo"),
-// getHTTPRequestParameter(request, "dstd"),
-// getHTTPRequestParameter(request, "dstActive"),
-// getHTTPRequestParameter(request, "curdate"),
-// getHTTPRequestParameter(request, "td") != null);
-// }
-// }
-//
-// @Override
-// public void processEvent(EventRequest request, EventResponse response)
-// throws PortletException, IOException {
-// handleRequest(request, response);
-// }
-//
-// private boolean handleURI(PortletCommunicationManager applicationManager,
-// Window window, ResourceRequest request, ResourceResponse response)
-// throws IOException {
-// // Handles the URI
-// DownloadStream download = applicationManager.handleURI(window, request,
-// response, this);
-//
-// // A download request
-// if (download != null) {
-// // Client downloads an resource
-// handleDownload(download, request, response);
-// return true;
-// }
-//
-// return false;
-// }
-//
-// private void handleDownload(DownloadStream stream, ResourceRequest request,
-// ResourceResponse response) throws IOException {
-//
-// if (stream.getParameter("Location") != null) {
-// response.setProperty(ResourceResponse.HTTP_STATUS_CODE,
-// Integer.toString(HttpServletResponse.SC_MOVED_TEMPORARILY));
-// response.setProperty("Location", stream.getParameter("Location"));
-// return;
-// }
-//
-// // Download from given stream
-// final InputStream data = stream.getStream();
-// if (data != null) {
-//
-// OutputStream out = null;
-// try {
-//
-// // Sets content type
-// response.setContentType(stream.getContentType());
-//
-// // Sets cache headers
-// final long cacheTime = stream.getCacheTime();
-// if (cacheTime <= 0) {
-// response.setProperty("Cache-Control", "no-cache");
-// response.setProperty("Pragma", "no-cache");
-// response.setProperty("Expires", "0");
-// } else {
-// response.setProperty("Cache-Control", "max-age="
-// + cacheTime / 1000);
-// response.setProperty("Expires",
-// "" + System.currentTimeMillis() + cacheTime);
-// // Required to apply caching in some Tomcats
-// response.setProperty("Pragma", "cache");
-// }
-//
-// // Copy download stream parameters directly
-// // to HTTP headers.
-// final Iterator<String> i = stream.getParameterNames();
-// if (i != null) {
-// while (i.hasNext()) {
-// final String param = i.next();
-// response.setProperty(param, stream.getParameter(param));
-// }
-// }
-//
-// // suggest local filename from DownloadStream if
-// // Content-Disposition
-// // not explicitly set
-// String contentDispositionValue = stream
-// .getParameter("Content-Disposition");
-// if (contentDispositionValue == null) {
-// contentDispositionValue = "filename=\""
-// + stream.getFileName() + "\"";
-// response.setProperty("Content-Disposition",
-// contentDispositionValue);
-// }
-//
-// int bufferSize = stream.getBufferSize();
-// if (bufferSize <= 0 || bufferSize > MAX_BUFFER_SIZE) {
-// bufferSize = DEFAULT_BUFFER_SIZE;
-// }
-// final byte[] buffer = new byte[bufferSize];
-// int bytesRead = 0;
-//
-// out = response.getPortletOutputStream();
-//
-// while ((bytesRead = data.read(buffer)) > 0) {
-// out.write(buffer, 0, bytesRead);
-// out.flush();
-// }
-// } finally {
-// AbstractCommunicationManager.tryToCloseStream(data);
-// AbstractCommunicationManager.tryToCloseStream(out);
-// }
-// }
-// }
-//
-// private void serveStaticResources(ResourceRequest request,
-// ResourceResponse response) throws IOException, PortletException {
-// final String resourceID = request.getResourceID();
-// final PortletContext pc = getPortletContext();
-//
-// InputStream is = pc.getResourceAsStream(resourceID);
-// if (is != null) {
-// final String mimetype = pc.getMimeType(resourceID);
-// if (mimetype != null) {
-// response.setContentType(mimetype);
-// }
-// final OutputStream os = response.getPortletOutputStream();
-// final byte buffer[] = new byte[DEFAULT_BUFFER_SIZE];
-// int bytes;
-// while ((bytes = is.read(buffer)) >= 0) {
-// os.write(buffer, 0, bytes);
-// }
-// } else {
-// logger.info("Requested resource [" + resourceID
-// + "] could not be found");
-// response.setProperty(ResourceResponse.HTTP_STATUS_CODE,
-// Integer.toString(HttpServletResponse.SC_NOT_FOUND));
-// }
-// }
-//
-// @Override
-// public void processAction(ActionRequest request, ActionResponse response)
-// throws PortletException, IOException {
-// handleRequest(request, response);
-// }
-//
-// @Override
-// protected void doDispatch(RenderRequest request, RenderResponse response)
-// throws PortletException, IOException {
-// try {
-// // try to let super handle - it'll call methods annotated for
-// // handling, the default doXYZ(), or throw if a handler for the mode
-// // is not found
-// super.doDispatch(request, response);
-//
-// } catch (PortletException e) {
-// if (e.getCause() == null) {
-// // No cause interpreted as 'unknown mode' - pass that trough
-// // so that the application can handle
-// handleRequest(request, response);
-//
-// } else {
-// // Something else failed, pass on
-// throw e;
-// }
-// }
-// }
-//
-// @Override
-// public void serveResource(ResourceRequest request, ResourceResponse response)
-// throws PortletException, IOException {
-// handleRequest(request, response);
-// }
-//
-// boolean requestCanCreateApplication(PortletRequest request,
-// RequestType requestType) {
-// if (requestType == RequestType.UIDL && isRepaintAll(request)) {
-// return true;
-// } else if (requestType == RequestType.RENDER) {
-// // In most cases the first request is a render request that renders
-// // the HTML fragment. This should create an application instance.
-// return true;
-// } else if (requestType == RequestType.EVENT) {
-// // A portlet can also be sent an event even though it has not been
-// // rendered, e.g. portlet on one page sends an event to a portlet on
-// // another page and then moves the user to that page.
-// return true;
-// }
-// return false;
-// }
-//
-// private boolean isRepaintAll(PortletRequest request) {
-// return (request.getParameter(URL_PARAMETER_REPAINT_ALL) != null)
-// && (request.getParameter(URL_PARAMETER_REPAINT_ALL).equals("1"));
-// }
-//
-// private void startApplication(PortletRequest request,
-// Application application, PortletApplicationContext2 context)
-// throws PortletException, MalformedURLException {
-// if (!application.isRunning()) {
-// Locale locale = request.getLocale();
-// application.setLocale(locale);
-// // No application URL when running inside a portlet
-// application.start(null, applicationProperties, context);
-// }
-// }
-//
-// private void endApplication(PortletRequest request,
-// PortletResponse response, Application application)
-// throws IOException {
-// final PortletSession session = request.getPortletSession();
-// if (session != null) {
-// getApplicationContext(session).removeApplication(application);
-// }
-// // Do not send any redirects when running inside a portlet.
-// }
-//
-// private Application findApplicationInstance(PortletRequest request,
-// RequestType requestType) throws PortletException,
-// SessionExpiredException, MalformedURLException {
-//
-// boolean requestCanCreateApplication = requestCanCreateApplication(
-// request, requestType);
-//
-// /* Find an existing application for this request. */
-// Application application = getExistingApplication(request,
-// requestCanCreateApplication);
-//
-// if (application != null) {
-// /*
-// * There is an existing application. We can use this as long as the
-// * user not specifically requested to close or restart it.
-// */
-//
-// final boolean restartApplication = (getHTTPRequestParameter(
-// request, URL_PARAMETER_RESTART_APPLICATION) != null);
-// final boolean closeApplication = (getHTTPRequestParameter(request,
-// URL_PARAMETER_CLOSE_APPLICATION) != null);
-//
-// if (restartApplication) {
-// closeApplication(application, request.getPortletSession(false));
-// return createApplication(request);
-// } else if (closeApplication) {
-// closeApplication(application, request.getPortletSession(false));
-// return null;
-// } else {
-// return application;
-// }
-// }
-//
-// // No existing application was found
-//
-// if (requestCanCreateApplication) {
-// return createApplication(request);
-// } else {
-// throw new SessionExpiredException();
-// }
-// }
-//
-// private void closeApplication(Application application,
-// PortletSession session) {
-// if (application == null) {
-// return;
-// }
-//
-// application.close();
-// if (session != null) {
-// PortletApplicationContext2 context = getApplicationContext(session);
-// context.removeApplication(application);
-// }
-// }
-//
-// private Application createApplication(PortletRequest request)
-// throws PortletException, MalformedURLException {
-// Application newApplication = getNewApplication(request);
-// final PortletApplicationContext2 context = getApplicationContext(request
-// .getPortletSession());
-// context.addApplication(newApplication, request.getWindowID());
-// return newApplication;
-// }
-//
-// private Application getExistingApplication(PortletRequest request,
-// boolean allowSessionCreation) throws MalformedURLException,
-// SessionExpiredException {
-//
-// final PortletSession session = request
-// .getPortletSession(allowSessionCreation);
-//
-// if (session == null) {
-// throw new SessionExpiredException();
-// }
-//
-// PortletApplicationContext2 context = getApplicationContext(session);
-// Application application = context.getApplicationForWindowId(request
-// .getWindowID());
-// if (application == null) {
-// return null;
-// }
-// if (application.isRunning()) {
-// return application;
-// }
-// // application found but not running
-// context.removeApplication(application);
-//
-// 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:
-// * <ul>
-// * <li>
-// * {@link #writeAjaxPageHtmlMainDiv(RenderRequest, RenderResponse, BufferedWriter, String)}
-// * <li>
-// * {@link #getVaadinConfigurationMap(RenderRequest, RenderResponse, Application, String)}
-// * <li>
-// * {@link #writeAjaxPageHtmlVaadinScripts(RenderRequest, RenderResponse, BufferedWriter, Application, String)}
-// * </ul>
-// *
-// * @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 {
-//
-// response.setContentType("text/html");
-// final BufferedWriter page = new BufferedWriter(new OutputStreamWriter(
-// response.getPortletOutputStream(), "UTF-8"));
-//
-// // TODO Currently, we can only load widgetsets and themes from the
-// // portal
-//
-// String themeName = getThemeForWindow(request, window);
-//
-// writeAjaxPageHtmlVaadinScripts(request, response, page, application,
-// themeName);
-//
-// /*- Add classnames;
-// * .v-app
-// * .v-app-loading
-// * .v-app-<simpleName for app class>
-// * .v-theme-<themeName, remove non-alphanum>
-// */
-// String appClass = "v-app-";
-// try {
-// appClass += getApplicationClass().getSimpleName();
-// } catch (ClassNotFoundException e) {
-// appClass += "unknown";
-// logger.log(Level.SEVERE, "Could not find application class", e);
-// }
-// String themeClass = "v-theme-"
-// + themeName.replaceAll("[^a-zA-Z0-9]", "");
-//
-// String classNames = "v-app " + themeClass + " " + appClass;
-//
-// String style = getApplicationProperty(PORTLET_PARAMETER_STYLE);
-// String divStyle = "";
-// if (style != null) {
-// divStyle = "style=\"" + style + "\"";
-// }
-//
-// writeAjaxPageHtmlMainDiv(request, response, page,
-// getApplicationDomId(request), classNames, divStyle);
-//
-// page.close();
-// }
-//
-// /**
-// * Creates and returns a unique ID for the DIV where the application is to
-// * be rendered. We need to generate a unique ID because some portals already
-// * create a DIV with the portlet's Window ID as the DOM ID.
-// *
-// * @param request
-// * PortletRequest
-// * @return the id to use in the DOM
-// */
-// private String getApplicationDomId(PortletRequest request) {
-// return "v-" + request.getWindowID();
-// }
-//
-// /**
-// * 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
-// // applications will load this exactly once
-// String portalTheme = getPortalProperty(PORTAL_PARAMETER_VAADIN_THEME,
-// request.getPortalContext());
-//
-// writer.write("<script type=\"text/javascript\">\n");
-// writer.write("if(!vaadin || !vaadin.vaadinConfigurations) {\n "
-// + "if(!vaadin) { var vaadin = {}} \n"
-// + "vaadin.vaadinConfigurations = {};\n"
-// + "if (!vaadin.themesLoaded) { vaadin.themesLoaded = {}; }\n");
-// if (!isProductionMode()) {
-// writer.write("vaadin.debug = true;\n");
-// }
-//
-// writeAjaxPageScriptWidgetset(request, response, writer);
-//
-// Map<String, String> config = getVaadinConfigurationMap(request,
-// response, application, themeURI);
-// writeAjaxPageScriptConfigurations(request, response, writer, config);
-//
-// writer.write("</script>\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('<iframe tabIndex=\"-1\" id=\"__gwt_historyFrame\" "
-// + "style=\"position:absolute;width:0;height:0;border:0;overflow:"
-// + "hidden;opacity:0;top:-100px;left:-100px;\" src=\"javascript:false\"></iframe>');\n");
-// writer.write("document.write(\"<script language='javascript' src='"
-// + widgetsetURL + "'><\\/script>\");\n}\n");
-// }
-//
-// /**
-// * Returns the configuration parameters to pass to the client.
-// *
-// * To add configuration parameters for the client, override, call the super
-// * method and then modify the map. Overriding this method may also require
-// * client side changes in {@link ApplicationConnection} and
-// * {@link ApplicationConfiguration}.
-// *
-// * Note that this method must escape and quote the values when appropriate.
-// *
-// * The map returned is typically a {@link LinkedHashMap} to preserve
-// * insertion order, but it is not guaranteed to be one.
-// *
-// * @param request
-// * @param response
-// * @param application
-// * @param themeURI
-// * @return modifiable Map from parameter name to its full value
-// * @throws PortletException
-// */
-// protected Map<String, String> getVaadinConfigurationMap(
-// RenderRequest request, RenderResponse response,
-// Application application, String themeURI) throws PortletException {
-// Map<String, String> config = new LinkedHashMap<String, String>();
-//
-// /*
-// * We need this in order to get uploads to work. TODO this is not needed
-// * for uploads anymore, check if this is needed for some other things
-// */
-// PortletURL appUri = response.createActionURL();
-// config.put("appUri", "'" + appUri.toString() + "'");
-// config.put("usePortletURLs", "true");
-// ResourceURL uidlUrlBase = response.createResourceURL();
-// uidlUrlBase.setResourceID("UIDL");
-// config.put("portletUidlURLBase", "'" + uidlUrlBase.toString() + "'");
-// config.put("pathInfo", "''");
-// config.put("themeUri", "'" + themeURI + "'");
-//
-// String versionInfo = "{vaadinVersion:\""
-// + AbstractApplicationServlet.VERSION
-// + "\",applicationVersion:\"" + application.getVersion() + "\"}";
-// config.put("versionInfo", versionInfo);
-//
-// // 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);
-// }
-// if (systemMessages != null) {
-// // Write the CommunicationError -message to client
-// String caption = systemMessages.getCommunicationErrorCaption();
-// if (caption != null) {
-// caption = "\"" + caption + "\"";
-// }
-// String message = systemMessages.getCommunicationErrorMessage();
-// if (message != null) {
-// message = "\"" + message + "\"";
-// }
-// String url = systemMessages.getCommunicationErrorURL();
-// if (url != null) {
-// url = "\"" + url + "\"";
-// }
-//
-// config.put("\"comErrMsg\"", "{" + "\"caption\":" + caption + ","
-// + "\"message\" : " + message + "," + "\"url\" : " + url
-// + "}");
-//
-// // Write the AuthenticationError -message to client
-// caption = systemMessages.getAuthenticationErrorCaption();
-// if (caption != null) {
-// caption = "\"" + caption + "\"";
-// }
-// message = systemMessages.getAuthenticationErrorMessage();
-// if (message != null) {
-// message = "\"" + message + "\"";
-// }
-// url = systemMessages.getAuthenticationErrorURL();
-// if (url != null) {
-// url = "\"" + url + "\"";
-// }
-//
-// config.put("\"authErrMsg\"", "{" + "\"caption\":" + caption + ","
-// + "\"message\" : " + message + "," + "\"url\" : " + url
-// + "}");
-// }
-//
-// return config;
-// }
-//
-// /**
-// * Constructs the Vaadin configuration section for
-// * {@link ApplicationConnection} and {@link ApplicationConfiguration}.
-// *
-// * Typically this method should not be overridden. Instead, modify
-// * {@link #getVaadinConfigurationMap(RenderRequest, RenderResponse, Application, String)}
-// * .
-// *
-// * @param request
-// * @param response
-// * @param writer
-// * @param config
-// * @throws IOException
-// * @throws PortletException
-// */
-// protected void writeAjaxPageScriptConfigurations(RenderRequest request,
-// RenderResponse response, final BufferedWriter writer,
-// Map<String, String> config) throws IOException, PortletException {
-//
-// writer.write("vaadin.vaadinConfigurations[\""
-// + getApplicationDomId(request) + "\"] = {");
-//
-// Iterator<String> keyIt = config.keySet().iterator();
-// while (keyIt.hasNext()) {
-// String key = keyIt.next();
-// writer.write(key + ": " + config.get(key));
-// if (keyIt.hasNext()) {
-// writer.write(", ");
-// }
-// }
-//
-// writer.write("};\n");
-// }
-//
-// /**
-// * Writes the Vaadin theme loading section of the portlet HTML. Loads both
-// * the portal theme and the portlet theme in this order, skipping loading of
-// * themes that are already loaded (matched by name).
-// *
-// * @param request
-// * @param writer
-// * @param themeName
-// * @param themeURI
-// * @param portalTheme
-// * @throws IOException
-// */
-// protected void writeAjaxPageHtmlTheme(RenderRequest request,
-// final BufferedWriter writer, String themeName, String themeURI,
-// String portalTheme) throws IOException {
-// writer.write("<script type=\"text/javascript\">\n");
-//
-// if (portalTheme == null) {
-// portalTheme = DEFAULT_THEME_NAME;
-// }
-//
-// writer.write("if(!vaadin.themesLoaded['" + portalTheme + "']) {\n");
-// writer.write("var defaultStylesheet = document.createElement('link');\n");
-// writer.write("defaultStylesheet.setAttribute('rel', 'stylesheet');\n");
-// writer.write("defaultStylesheet.setAttribute('type', 'text/css');\n");
-// writer.write("defaultStylesheet.setAttribute('href', '"
-// + getThemeURI(portalTheme, request) + "/styles.css');\n");
-// writer.write("document.getElementsByTagName('head')[0].appendChild(defaultStylesheet);\n");
-// writer.write("vaadin.themesLoaded['" + portalTheme + "'] = true;\n}\n");
-//
-// if (!portalTheme.equals(themeName)) {
-// writer.write("if(!vaadin.themesLoaded['" + themeName + "']) {\n");
-// writer.write("var stylesheet = document.createElement('link');\n");
-// writer.write("stylesheet.setAttribute('rel', 'stylesheet');\n");
-// writer.write("stylesheet.setAttribute('type', 'text/css');\n");
-// writer.write("stylesheet.setAttribute('href', '" + themeURI
-// + "/styles.css');\n");
-// writer.write("document.getElementsByTagName('head')[0].appendChild(stylesheet);\n");
-// writer.write("vaadin.themesLoaded['" + themeName
-// + "'] = true;\n}\n");
-// }
-//
-// writer.write("</script>\n");
-// }
-//
-// /**
-// * 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 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("<div id=\"" + id + "\" class=\"" + classNames + "\" "
-// + divStyle + ">");
-// writer.write("<div class=\"v-app-loading\"></div>");
-// writer.write("</div>\n");
-// writer.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 theme for given request/window
-// *
-// * @param request
-// * @param window
-// * @return
-// */
-// protected String getThemeForWindow(PortletRequest request, Window window) {
-// // Finds theme name
-// String themeName;
-//
-// // theme defined for the window?
-// themeName = window.getTheme();
-//
-// if (themeName == null) {
-// // no, is the default theme defined by the portal?
-// themeName = getPortalProperty(
-// Constants.PORTAL_PARAMETER_VAADIN_THEME,
-// request.getPortalContext());
-// }
-//
-// if (themeName == null) {
-// // no, using the default theme defined by Vaadin
-// themeName = DEFAULT_THEME_NAME;
-// }
-//
-// return themeName;
-// }
-//
-// protected abstract Class<? extends Application> getApplicationClass()
-// throws ClassNotFoundException;
-//
-// protected Application getNewApplication(PortletRequest request)
-// throws PortletException {
-// try {
-// final Application application = getApplicationClass().newInstance();
-// return application;
-// } catch (final IllegalAccessException e) {
-// throw new PortletException("getNewApplication failed", e);
-// } catch (final InstantiationException e) {
-// throw new PortletException("getNewApplication failed", e);
-// } catch (final ClassNotFoundException e) {
-// throw new PortletException("getNewApplication failed", e);
-// }
-// }
-//
-// protected ClassLoader getClassLoader() throws PortletException {
-// // TODO Add support for custom class loader
-// return getClass().getClassLoader();
-// }
-//
-// /**
-// * Get system messages from the current application class
-// *
-// * @return
-// */
-// protected SystemMessages getSystemMessages() {
-// try {
-// Class<? extends Application> appCls = getApplicationClass();
-// Method m = appCls.getMethod("getSystemMessages", (Class[]) null);
-// return (Application.SystemMessages) m.invoke(null, (Object[]) null);
-// } catch (ClassNotFoundException e) {
-// // This should never happen
-// throw new SystemMessageException(e);
-// } catch (SecurityException e) {
-// throw new SystemMessageException(
-// "Application.getSystemMessage() should be static public", e);
-// } catch (NoSuchMethodException e) {
-// // This is completely ok and should be silently ignored
-// } catch (IllegalArgumentException e) {
-// // This should never happen
-// throw new SystemMessageException(e);
-// } catch (IllegalAccessException e) {
-// throw new SystemMessageException(
-// "Application.getSystemMessage() should be static public", e);
-// } catch (InvocationTargetException e) {
-// // This should never happen
-// throw new SystemMessageException(e);
-// }
-// return Application.getSystemMessages();
-// }
-//
-// private void handleServiceException(PortletRequest request,
-// PortletResponse response, Application application, Throwable e)
-// throws IOException, PortletException {
-// // TODO Check that this error handler is working when running inside a
-// // portlet
-//
-// // if this was an UIDL request, response UIDL back to client
-// if (getRequestType(request) == RequestType.UIDL) {
-// Application.SystemMessages ci = getSystemMessages();
-// criticalNotification(request, (ResourceResponse) response,
-// ci.getInternalErrorCaption(), ci.getInternalErrorMessage(),
-// null, ci.getInternalErrorURL());
-// if (application != null) {
-// application.getErrorHandler()
-// .terminalError(new RequestError(e));
-// } else {
-// throw new PortletException(e);
-// }
-// } else {
-// // Re-throw other exceptions
-// throw new PortletException(e);
-// }
-//
-// }
-//
-// @SuppressWarnings("serial")
-// public class RequestError implements Terminal.ErrorEvent, Serializable {
-//
-// private final Throwable throwable;
-//
-// public RequestError(Throwable throwable) {
-// this.throwable = throwable;
-// }
-//
-// public Throwable getThrowable() {
-// return throwable;
-// }
-//
-// }
-//
-// /**
-// * Send notification to client's application. Used to notify client of
-// * critical errors and session expiration due to long inactivity. Server has
-// * no knowledge of what application client refers to.
-// *
-// * @param request
-// * the Portlet request instance.
-// * @param response
-// * the Portlet response to write to.
-// * @param caption
-// * for the notification
-// * @param message
-// * for the notification
-// * @param details
-// * a detail message to show in addition to the passed message.
-// * Currently shown directly but could be hidden behind a details
-// * drop down.
-// * @param url
-// * url to load after message, null for current page
-// * @throws IOException
-// * if the writing failed due to input/output error.
-// */
-// void criticalNotification(PortletRequest request, MimeResponse response,
-// String caption, String message, String details, String url)
-// throws IOException {
-//
-// // clients JS app is still running, but server application either
-// // no longer exists or it might fail to perform reasonably.
-// // send a notification to client's application and link how
-// // to "restart" application.
-//
-// if (caption != null) {
-// caption = "\"" + caption + "\"";
-// }
-// if (details != null) {
-// if (message == null) {
-// message = details;
-// } else {
-// message += "<br/><br/>" + details;
-// }
-// }
-// if (message != null) {
-// message = "\"" + message + "\"";
-// }
-// if (url != null) {
-// url = "\"" + url + "\"";
-// }
-//
-// // Set the response type
-// response.setContentType("application/json; charset=UTF-8");
-// final OutputStream out = response.getPortletOutputStream();
-// final PrintWriter outWriter = new PrintWriter(new BufferedWriter(
-// new OutputStreamWriter(out, "UTF-8")));
-// outWriter.print("for(;;);[{\"changes\":[], \"meta\" : {"
-// + "\"appError\": {" + "\"caption\":" + caption + ","
-// + "\"message\" : " + message + "," + "\"url\" : " + url
-// + "}}, \"resources\": {}, \"locales\":[]}]");
-// outWriter.close();
-// }
-//
-// /**
-// * 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");
-//
-// // TODO test on non-LifeRay platforms
-//
-// String value;
-// if (isLifeRay) {
-// value = getLifeRayPortalProperty(name);
-// } else {
-// value = context.getProperty(name);
-// }
-//
-// return value;
-// }
-//
-// private static String getLifeRayPortalProperty(String name) {
-// String value;
-// try {
-// value = PropsUtil.get(name);
-// } catch (Exception e) {
-// value = null;
-// }
-// return value;
-// }
-//
-// /**
-// * Try to get an HTTP header value from a request using portal specific
-// * APIs.
-// *
-// * @param name
-// * HTTP header name
-// * @return the value of the header (empty string if defined without a value,
-// * null if the parameter is not present or retrieving it failed)
-// */
-// private static String getHTTPHeader(PortletRequest request, String name) {
-// String value = null;
-// String portalInfo = request.getPortalContext().getPortalInfo()
-// .toLowerCase();
-// if (portalInfo.contains("liferay")) {
-// value = getLiferayHTTPHeader(request, name);
-// } else if (portalInfo.contains("gatein")) {
-// value = getGateInHTTPHeader(request, name);
-// }
-// return value;
-// }
-//
-// /**
-// * Try to get the value of a HTTP request parameter from a portlet request
-// * using portal specific APIs. It is not possible to get the HTTP request
-// * parameters using the official Portlet 2.0 API.
-// *
-// * @param name
-// * HTTP request parameter name
-// * @return the value of the parameter (empty string if parameter defined
-// * without a value, null if the parameter is not present or
-// * retrieving it failed)
-// */
-// private static String getHTTPRequestParameter(PortletRequest request,
-// String name) {
-// String value = request.getParameter(name);
-// if (value == null) {
-// String portalInfo = request.getPortalContext().getPortalInfo()
-// .toLowerCase();
-// if (portalInfo.contains("liferay")) {
-// value = getLiferayHTTPRequestParameter(request, name);
-// } else if (portalInfo.contains("gatein")) {
-// value = getGateInHTTPRequestParameter(request, name);
-// }
-// }
-// return value;
-// }
-//
-// private static String getGateInHTTPRequestParameter(PortletRequest request,
-// String name) {
-// String value = null;
-// try {
-// Method getRealReq = request.getClass().getMethod("getRealRequest");
-// HttpServletRequestWrapper origRequest = (HttpServletRequestWrapper) getRealReq
-// .invoke(request);
-// value = origRequest.getParameter(name);
-// } catch (Exception e) {
-// // do nothing - not on GateIn simple-portal
-// }
-// return value;
-// }
-//
-// private static String getLiferayHTTPRequestParameter(
-// PortletRequest request, String name) {
-// try {
-// // httpRequest = PortalUtil.getHttpServletRequest(request);
-// HttpServletRequest httpRequest = (HttpServletRequest) PortalClassInvoker
-// .invoke("com.liferay.portal.util.PortalUtil",
-// "getHttpServletRequest", request);
-//
-// // httpRequest =
-// // PortalUtil.getOriginalServletRequest(httpRequest);
-// httpRequest = (HttpServletRequest) PortalClassInvoker.invoke(
-// "com.liferay.portal.util.PortalUtil",
-// "getOriginalServletRequest", httpRequest);
-// if (httpRequest != null) {
-// return httpRequest.getParameter(name);
-// }
-// } catch (Exception e) {
-// // ignore and return null - unable to get the original request
-// }
-// return null;
-// }
-//
-// private static String getGateInHTTPHeader(PortletRequest request,
-// String name) {
-// String value = null;
-// try {
-// Method getRealReq = request.getClass().getMethod("getRealRequest");
-// HttpServletRequestWrapper origRequest = (HttpServletRequestWrapper) getRealReq
-// .invoke(request);
-// value = origRequest.getHeader(name);
-// } catch (Exception e) {
-// // do nothing - not on GateIn simple-portal
-// }
-// return value;
-// }
-//
-// private static String getLiferayHTTPHeader(PortletRequest request,
-// String name) {
-// try {
-// // httpRequest = PortalUtil.getHttpServletRequest(request);
-// HttpServletRequest httpRequest = (HttpServletRequest) PortalClassInvoker
-// .invoke("com.liferay.portal.util.PortalUtil",
-// "getHttpServletRequest", request);
-//
-// // httpRequest =
-// // PortalUtil.getOriginalServletRequest(httpRequest);
-// httpRequest = (HttpServletRequest) PortalClassInvoker.invoke(
-// "com.liferay.portal.util.PortalUtil",
-// "getOriginalServletRequest", httpRequest);
-// if (httpRequest != null) {
-// return httpRequest.getHeader(name);
-// }
-// } catch (Exception e) {
-// // ignore and return null - unable to get the original request
-// }
-// return null;
-// }
-//
-// /**
-// *
-// * Gets the application context for a PortletSession. If no context is
-// * currently stored in a session a new context is created and stored in the
-// * session.
-// *
-// * @param portletSession
-// * the portlet session.
-// * @return the application context for the session.
-// */
-// protected PortletApplicationContext2 getApplicationContext(
-// PortletSession portletSession) {
-// return PortletApplicationContext2.getApplicationContext(portletSession);
-// }
-//
-// }
+package com.vaadin.terminal.gwt.server;
+
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.MalformedURLException;
+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;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.portlet.ActionRequest;
+import javax.portlet.ActionResponse;
+import javax.portlet.EventRequest;
+import javax.portlet.EventResponse;
+import javax.portlet.GenericPortlet;
+import javax.portlet.MimeResponse;
+import javax.portlet.PortalContext;
+import javax.portlet.PortletConfig;
+import javax.portlet.PortletContext;
+import javax.portlet.PortletException;
+import javax.portlet.PortletRequest;
+import javax.portlet.PortletResponse;
+import javax.portlet.PortletSession;
+import javax.portlet.PortletURL;
+import javax.portlet.RenderRequest;
+import javax.portlet.RenderResponse;
+import javax.portlet.ResourceRequest;
+import javax.portlet.ResourceResponse;
+import javax.portlet.ResourceURL;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import javax.servlet.http.HttpServletResponse;
+
+import com.liferay.portal.kernel.util.PortalClassInvoker;
+import com.liferay.portal.kernel.util.PropsUtil;
+import com.vaadin.Application;
+import com.vaadin.Application.SystemMessages;
+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.Root;
+
+/**
+ * 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
+ */
+public abstract class AbstractApplicationPortlet extends GenericPortlet
+ implements Constants {
+
+ private static final Logger logger = Logger
+ .getLogger(AbstractApplicationPortlet.class.getName());
+
+ /**
+ * This portlet parameter is used to add styles to the main element. E.g
+ * "height:500px" generates a style="height:500px" to the main element.
+ */
+ public static final String PORTLET_PARAMETER_STYLE = "style";
+
+ private static final String PORTAL_PARAMETER_VAADIN_THEME = "vaadin.theme";
+
+ // TODO some parts could be shared with AbstractApplicationServlet
+
+ // TODO Can we close the application when the portlet is removed? Do we know
+ // when the portlet is removed?
+
+ // TODO What happens when the portlet window is resized? Do we know when the
+ // window is resized?
+
+ private Properties applicationProperties;
+
+ private boolean productionMode = false;
+
+ @Override
+ public void init(PortletConfig config) throws PortletException {
+ super.init(config);
+ // Stores the application parameters into Properties object
+ applicationProperties = new Properties();
+ for (final Enumeration<String> e = config.getInitParameterNames(); e
+ .hasMoreElements();) {
+ final String name = e.nextElement();
+ applicationProperties.setProperty(name,
+ config.getInitParameter(name));
+ }
+
+ // Overrides with server.xml parameters
+ final PortletContext context = config.getPortletContext();
+ for (final Enumeration<String> e = context.getInitParameterNames(); e
+ .hasMoreElements();) {
+ final String name = e.nextElement();
+ applicationProperties.setProperty(name,
+ context.getInitParameter(name));
+ }
+ checkProductionMode();
+ checkCrossSiteProtection();
+ }
+
+ private void checkCrossSiteProtection() {
+ if (getApplicationOrSystemProperty(
+ SERVLET_PARAMETER_DISABLE_XSRF_PROTECTION, "false").equals(
+ "true")) {
+ /*
+ * Print an information/warning message about running with xsrf
+ * protection disabled
+ */
+ logger.warning(WARNING_XSRF_PROTECTION_DISABLED);
+ }
+ }
+
+ /**
+ * Checks that the version reported by the client (widgetset) matches that
+ * of the server.
+ *
+ * @param request
+ */
+ private void checkWidgetsetVersion(PortletRequest request) {
+ if (!AbstractApplicationServlet.VERSION.equals(getHTTPRequestParameter(
+ request, "wsver"))) {
+ logger.warning(String.format(WIDGETSET_MISMATCH_INFO,
+ AbstractApplicationServlet.VERSION,
+ getHTTPRequestParameter(request, "wsver")));
+ }
+ }
+
+ private void checkProductionMode() {
+ // Check if the application is in production mode.
+ // We are in production mode if Debug=false or productionMode=true
+ if (getApplicationOrSystemProperty(SERVLET_PARAMETER_DEBUG, "true")
+ .equals("false")) {
+ // "Debug=true" is the old way and should no longer be used
+ productionMode = true;
+ } else if (getApplicationOrSystemProperty(
+ SERVLET_PARAMETER_PRODUCTION_MODE, "false").equals("true")) {
+ // "productionMode=true" is the real way to do it
+ productionMode = true;
+ }
+
+ if (!productionMode) {
+ /* Print an information/warning message about running in debug mode */
+ // TODO Maybe we need a different message for portlets?
+ logger.warning(NOT_PRODUCTION_MODE_INFO);
+ }
+ }
+
+ /**
+ * Gets an application property value.
+ *
+ * @param parameterName
+ * the Name or the parameter.
+ * @return String value or null if not found
+ */
+ protected String getApplicationProperty(String parameterName) {
+
+ String val = applicationProperties.getProperty(parameterName);
+ if (val != null) {
+ return val;
+ }
+
+ // Try lower case application properties for backward compatibility with
+ // 3.0.2 and earlier
+ val = applicationProperties.getProperty(parameterName.toLowerCase());
+
+ return val;
+ }
+
+ /**
+ * Gets an system property value.
+ *
+ * @param parameterName
+ * the Name or the parameter.
+ * @return String value or null if not found
+ */
+ protected String getSystemProperty(String parameterName) {
+ String val = null;
+
+ String pkgName;
+ final Package pkg = getClass().getPackage();
+ if (pkg != null) {
+ pkgName = pkg.getName();
+ } else {
+ final String className = getClass().getName();
+ pkgName = new String(className.toCharArray(), 0,
+ className.lastIndexOf('.'));
+ }
+ val = System.getProperty(pkgName + "." + parameterName);
+ if (val != null) {
+ return val;
+ }
+
+ // Try lowercased system properties
+ val = System.getProperty(pkgName + "." + parameterName.toLowerCase());
+ return val;
+ }
+
+ /**
+ * Gets an application or system property value.
+ *
+ * @param parameterName
+ * the Name or the parameter.
+ * @param defaultValue
+ * the Default to be used.
+ * @return String value or default if not found
+ */
+ protected String getApplicationOrSystemProperty(String parameterName,
+ String defaultValue) {
+
+ String val = null;
+
+ // Try application properties
+ val = getApplicationProperty(parameterName);
+ if (val != null) {
+ return val;
+ }
+
+ // Try system properties
+ val = getSystemProperty(parameterName);
+ if (val != null) {
+ return val;
+ }
+
+ return defaultValue;
+ }
+
+ /**
+ * Return the URL from where static files, e.g. the widgetset and the theme,
+ * are served. In a standard configuration the VAADIN folder inside the
+ * returned folder is what is used for widgetsets and themes.
+ *
+ * @param request
+ * @return The location of static resources (inside which there should be a
+ * VAADIN directory). Does not end with a slash (/).
+ */
+ protected String getStaticFilesLocation(PortletRequest request) {
+ // TODO allow overriding on portlet level?
+ String staticFileLocation = getPortalProperty(
+ Constants.PORTAL_PARAMETER_VAADIN_RESOURCE_PATH,
+ request.getPortalContext());
+ if (staticFileLocation != null) {
+ // remove trailing slash if any
+ while (staticFileLocation.endsWith(".")) {
+ staticFileLocation = staticFileLocation.substring(0,
+ staticFileLocation.length() - 1);
+ }
+ return staticFileLocation;
+ } else {
+ // default for Liferay
+ return "/html";
+ }
+ }
+
+ protected enum RequestType {
+ FILE_UPLOAD, UIDL, RENDER, STATIC_FILE, APPLICATION_RESOURCE, DUMMY, EVENT, ACTION, UNKNOWN;
+ }
+
+ protected RequestType getRequestType(PortletRequest request) {
+ if (request instanceof RenderRequest) {
+ return RequestType.RENDER;
+ } else if (request instanceof ResourceRequest) {
+ if (isUIDLRequest((ResourceRequest) request)) {
+ return RequestType.UIDL;
+ } else if (isFileUploadRequest((ResourceRequest) request)) {
+ return RequestType.FILE_UPLOAD;
+ } else if (isApplicationResourceRequest((ResourceRequest) request)) {
+ return RequestType.APPLICATION_RESOURCE;
+ } else if (isDummyRequest((ResourceRequest) request)) {
+ return RequestType.DUMMY;
+ } else {
+ return RequestType.STATIC_FILE;
+ }
+ } else if (request instanceof ActionRequest) {
+ return RequestType.ACTION;
+ } else if (request instanceof EventRequest) {
+ return RequestType.EVENT;
+ }
+ return RequestType.UNKNOWN;
+ }
+
+ private boolean isApplicationResourceRequest(ResourceRequest request) {
+ return request.getResourceID() != null
+ && request.getResourceID().startsWith("APP");
+ }
+
+ private boolean isUIDLRequest(ResourceRequest request) {
+ return request.getResourceID() != null
+ && request.getResourceID().equals("UIDL");
+ }
+
+ private boolean isDummyRequest(ResourceRequest request) {
+ return request.getResourceID() != null
+ && request.getResourceID().equals("DUMMY");
+ }
+
+ private boolean isFileUploadRequest(ResourceRequest request) {
+ return "UPLOAD".equals(request.getResourceID());
+ }
+
+ /**
+ * Returns true if the servlet is running in production mode. Production
+ * mode disables all debug facilities.
+ *
+ * @return true if in production mode, false if in debug mode
+ */
+ public boolean isProductionMode() {
+ return productionMode;
+ }
+
+ protected void handleRequest(PortletRequest request,
+ PortletResponse response) throws PortletException, IOException {
+ RequestType requestType = getRequestType(request);
+
+ if (requestType == RequestType.UNKNOWN) {
+ handleUnknownRequest(request, response);
+ } else if (requestType == RequestType.DUMMY) {
+ /*
+ * This dummy page is used by action responses to redirect to, in
+ * order to prevent the boot strap code from being rendered into
+ * strange places such as iframes.
+ */
+ ((ResourceResponse) response).setContentType("text/html");
+ final OutputStream out = ((ResourceResponse) response)
+ .getPortletOutputStream();
+ final PrintWriter outWriter = new PrintWriter(new BufferedWriter(
+ new OutputStreamWriter(out, "UTF-8")));
+ outWriter.print("<html><body>dummy page</body></html>");
+ outWriter.close();
+ } else if (requestType == RequestType.STATIC_FILE) {
+ serveStaticResources((ResourceRequest) request,
+ (ResourceResponse) response);
+ } else {
+ Application application = null;
+ boolean transactionStarted = false;
+ boolean requestStarted = false;
+
+ try {
+ // TODO What about PARAM_UNLOADBURST & redirectToApplication??
+
+ /* Find out which application this request is related to */
+ application = findApplicationInstance(request, requestType);
+ if (application == null) {
+ return;
+ }
+
+ /*
+ * Get or create an application context and an application
+ * manager for the session
+ */
+ PortletApplicationContext2 applicationContext = getApplicationContext(request
+ .getPortletSession());
+ applicationContext.setResponse(response);
+ applicationContext.setPortletConfig(getPortletConfig());
+
+ PortletCommunicationManager applicationManager = applicationContext
+ .getApplicationManager(application);
+
+ /* Update browser information from request */
+ updateBrowserProperties(applicationContext.getBrowser(),
+ request);
+
+ /*
+ * Call application requestStart before Application.init() is
+ * called (bypasses the limitation in TransactionListener)
+ */
+ if (application instanceof PortletRequestListener) {
+ ((PortletRequestListener) application).onRequestStart(
+ request, response);
+ requestStarted = true;
+ }
+
+ /* Start the newly created application */
+ startApplication(request, application, applicationContext);
+
+ /*
+ * Transaction starts. Call transaction listeners. Transaction
+ * end is called in the finally block below.
+ */
+ applicationContext.startTransaction(application, request);
+ transactionStarted = true;
+
+ /* Notify listeners */
+
+ // Finds the window within the application
+ Root root = null;
+ synchronized (application) {
+ if (application.isRunning()) {
+ switch (requestType) {
+ case FILE_UPLOAD:
+ // no window
+ break;
+ case APPLICATION_RESOURCE:
+ // use main window - should not need any window
+ root = application.getRoot();
+ break;
+ default:
+ root = applicationManager.getApplicationRoot(
+ request, this, application, null);
+ }
+ // if window not found, not a problem - use null
+ }
+ }
+
+ // TODO Should this happen before or after the transaction
+ // starts?
+ if (request instanceof RenderRequest) {
+ applicationContext.firePortletRenderRequest(application,
+ root, (RenderRequest) request,
+ (RenderResponse) response);
+ } else if (request instanceof ActionRequest) {
+ applicationContext.firePortletActionRequest(application,
+ root, (ActionRequest) request,
+ (ActionResponse) response);
+ } else if (request instanceof EventRequest) {
+ applicationContext.firePortletEventRequest(application,
+ root, (EventRequest) request,
+ (EventResponse) response);
+ } else if (request instanceof ResourceRequest) {
+ applicationContext.firePortletResourceRequest(application,
+ root, (ResourceRequest) request,
+ (ResourceResponse) response);
+ }
+
+ /* Handle the request */
+ if (requestType == RequestType.FILE_UPLOAD) {
+ applicationManager.handleFileUpload(
+ (ResourceRequest) request,
+ (ResourceResponse) response);
+ return;
+ } else if (requestType == RequestType.UIDL) {
+ // Handles AJAX UIDL requests
+ if (isRepaintAll(request)) {
+ // warn if versions do not match
+ checkWidgetsetVersion(request);
+ }
+ applicationManager.handleUidlRequest(
+ (ResourceRequest) request,
+ (ResourceResponse) response, this, root);
+ return;
+ } else {
+ /*
+ * Removes the application if it has stopped
+ */
+ if (!application.isRunning()) {
+ endApplication(request, response, application);
+ return;
+ }
+
+ handleOtherRequest(request, response, requestType,
+ application, root, applicationContext,
+ applicationManager);
+ }
+ } catch (final SessionExpiredException e) {
+ // TODO Figure out a better way to deal with
+ // SessionExpiredExceptions
+ logger.finest("A user session has expired");
+ } catch (final GeneralSecurityException e) {
+ // TODO Figure out a better way to deal with
+ // GeneralSecurityExceptions
+ logger.fine("General security exception, the security key was probably incorrect.");
+ } catch (final Throwable e) {
+ handleServiceException(request, response, application, e);
+ } finally {
+ // Notifies transaction end
+ try {
+ if (transactionStarted) {
+ ((PortletApplicationContext2) application.getContext())
+ .endTransaction(application, request);
+ }
+ } finally {
+ if (requestStarted) {
+ ((PortletRequestListener) application).onRequestEnd(
+ request, response);
+
+ }
+ }
+ }
+ }
+ }
+
+ private void handleUnknownRequest(PortletRequest request,
+ PortletResponse response) {
+ logger.warning("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
+ */
+ private void handleOtherRequest(PortletRequest request,
+ PortletResponse response, RequestType requestType,
+ Application application, Root root,
+ PortletApplicationContext2 applicationContext,
+ PortletCommunicationManager applicationManager)
+ throws PortletException, IOException, MalformedURLException {
+ if (root == null) {
+ throw new PortletException(ERROR_NO_WINDOW_FOUND);
+ }
+
+ /*
+ * Sets terminal type for the window, if not already set
+ */
+ if (root.getTerminal() == null) {
+ root.setTerminal(applicationContext.getBrowser());
+ }
+
+ /*
+ * Handle parameters
+ */
+ // final Map<String, String[]> parameters = request.getParameterMap();
+ // if (root != null && parameters != null) {
+ // root.handleParameters(parameters);
+ // }
+
+ if (requestType == RequestType.APPLICATION_RESOURCE) {
+ handleURI(applicationManager, root, (ResourceRequest) request,
+ (ResourceResponse) response);
+ } else if (requestType == RequestType.RENDER) {
+ writeAjaxPage((RenderRequest) request, (RenderResponse) response,
+ root, 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) {
+ String userAgent = getHTTPHeader(request, "user-agent");
+ browser.updateRequestDetails(request.getLocale(), null,
+ request.isSecure(), userAgent);
+ if (getHTTPRequestParameter(request, "repaintAll") != null) {
+ browser.updateClientSideDetails(
+ getHTTPRequestParameter(request, "sw"),
+ getHTTPRequestParameter(request, "sh"),
+ getHTTPRequestParameter(request, "tzo"),
+ getHTTPRequestParameter(request, "rtzo"),
+ getHTTPRequestParameter(request, "dstd"),
+ getHTTPRequestParameter(request, "dstActive"),
+ getHTTPRequestParameter(request, "curdate"),
+ getHTTPRequestParameter(request, "td") != null);
+ }
+ }
+
+ @Override
+ public void processEvent(EventRequest request, EventResponse response)
+ throws PortletException, IOException {
+ handleRequest(request, response);
+ }
+
+ private boolean handleURI(PortletCommunicationManager applicationManager,
+ Root root, ResourceRequest request, ResourceResponse response)
+ throws IOException {
+ // Handles the URI
+ DownloadStream download = applicationManager.handleURI(root, request,
+ response, this);
+
+ // A download request
+ if (download != null) {
+ // Client downloads an resource
+ handleDownload(download, request, response);
+ return true;
+ }
+
+ return false;
+ }
+
+ private void handleDownload(DownloadStream stream, ResourceRequest request,
+ ResourceResponse response) throws IOException {
+
+ if (stream.getParameter("Location") != null) {
+ response.setProperty(ResourceResponse.HTTP_STATUS_CODE,
+ Integer.toString(HttpServletResponse.SC_MOVED_TEMPORARILY));
+ response.setProperty("Location", stream.getParameter("Location"));
+ return;
+ }
+
+ // Download from given stream
+ final InputStream data = stream.getStream();
+ if (data != null) {
+
+ OutputStream out = null;
+ try {
+
+ // Sets content type
+ response.setContentType(stream.getContentType());
+
+ // Sets cache headers
+ final long cacheTime = stream.getCacheTime();
+ if (cacheTime <= 0) {
+ response.setProperty("Cache-Control", "no-cache");
+ response.setProperty("Pragma", "no-cache");
+ response.setProperty("Expires", "0");
+ } else {
+ response.setProperty("Cache-Control", "max-age="
+ + cacheTime / 1000);
+ response.setProperty("Expires",
+ "" + System.currentTimeMillis() + cacheTime);
+ // Required to apply caching in some Tomcats
+ response.setProperty("Pragma", "cache");
+ }
+
+ // Copy download stream parameters directly
+ // to HTTP headers.
+ final Iterator<String> i = stream.getParameterNames();
+ if (i != null) {
+ while (i.hasNext()) {
+ final String param = i.next();
+ response.setProperty(param, stream.getParameter(param));
+ }
+ }
+
+ // suggest local filename from DownloadStream if
+ // Content-Disposition
+ // not explicitly set
+ String contentDispositionValue = stream
+ .getParameter("Content-Disposition");
+ if (contentDispositionValue == null) {
+ contentDispositionValue = "filename=\""
+ + stream.getFileName() + "\"";
+ response.setProperty("Content-Disposition",
+ contentDispositionValue);
+ }
+
+ int bufferSize = stream.getBufferSize();
+ if (bufferSize <= 0 || bufferSize > MAX_BUFFER_SIZE) {
+ bufferSize = DEFAULT_BUFFER_SIZE;
+ }
+ final byte[] buffer = new byte[bufferSize];
+ int bytesRead = 0;
+
+ out = response.getPortletOutputStream();
+
+ while ((bytesRead = data.read(buffer)) > 0) {
+ out.write(buffer, 0, bytesRead);
+ out.flush();
+ }
+ } finally {
+ AbstractCommunicationManager.tryToCloseStream(data);
+ AbstractCommunicationManager.tryToCloseStream(out);
+ }
+ }
+ }
+
+ private void serveStaticResources(ResourceRequest request,
+ ResourceResponse response) throws IOException, PortletException {
+ final String resourceID = request.getResourceID();
+ final PortletContext pc = getPortletContext();
+
+ InputStream is = pc.getResourceAsStream(resourceID);
+ if (is != null) {
+ final String mimetype = pc.getMimeType(resourceID);
+ if (mimetype != null) {
+ response.setContentType(mimetype);
+ }
+ final OutputStream os = response.getPortletOutputStream();
+ final byte buffer[] = new byte[DEFAULT_BUFFER_SIZE];
+ int bytes;
+ while ((bytes = is.read(buffer)) >= 0) {
+ os.write(buffer, 0, bytes);
+ }
+ } else {
+ logger.info("Requested resource [" + resourceID
+ + "] could not be found");
+ response.setProperty(ResourceResponse.HTTP_STATUS_CODE,
+ Integer.toString(HttpServletResponse.SC_NOT_FOUND));
+ }
+ }
+
+ @Override
+ public void processAction(ActionRequest request, ActionResponse response)
+ throws PortletException, IOException {
+ handleRequest(request, response);
+ }
+
+ @Override
+ protected void doDispatch(RenderRequest request, RenderResponse response)
+ throws PortletException, IOException {
+ try {
+ // try to let super handle - it'll call methods annotated for
+ // handling, the default doXYZ(), or throw if a handler for the mode
+ // is not found
+ super.doDispatch(request, response);
+
+ } catch (PortletException e) {
+ if (e.getCause() == null) {
+ // No cause interpreted as 'unknown mode' - pass that trough
+ // so that the application can handle
+ handleRequest(request, response);
+
+ } else {
+ // Something else failed, pass on
+ throw e;
+ }
+ }
+ }
+
+ @Override
+ public void serveResource(ResourceRequest request, ResourceResponse response)
+ throws PortletException, IOException {
+ handleRequest(request, response);
+ }
+
+ boolean requestCanCreateApplication(PortletRequest request,
+ RequestType requestType) {
+ if (requestType == RequestType.UIDL && isRepaintAll(request)) {
+ return true;
+ } else if (requestType == RequestType.RENDER) {
+ // In most cases the first request is a render request that renders
+ // the HTML fragment. This should create an application instance.
+ return true;
+ } else if (requestType == RequestType.EVENT) {
+ // A portlet can also be sent an event even though it has not been
+ // rendered, e.g. portlet on one page sends an event to a portlet on
+ // another page and then moves the user to that page.
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isRepaintAll(PortletRequest request) {
+ return (request.getParameter(URL_PARAMETER_REPAINT_ALL) != null)
+ && (request.getParameter(URL_PARAMETER_REPAINT_ALL).equals("1"));
+ }
+
+ private void startApplication(PortletRequest request,
+ Application application, PortletApplicationContext2 context)
+ throws PortletException, MalformedURLException {
+ if (!application.isRunning()) {
+ Locale locale = request.getLocale();
+ application.setLocale(locale);
+ // No application URL when running inside a portlet
+ application.start(null, applicationProperties, context);
+ }
+ }
+
+ private void endApplication(PortletRequest request,
+ PortletResponse response, Application application)
+ throws IOException {
+ final PortletSession session = request.getPortletSession();
+ if (session != null) {
+ getApplicationContext(session).removeApplication(application);
+ }
+ // Do not send any redirects when running inside a portlet.
+ }
+
+ private Application findApplicationInstance(PortletRequest request,
+ RequestType requestType) throws PortletException,
+ SessionExpiredException, MalformedURLException {
+
+ boolean requestCanCreateApplication = requestCanCreateApplication(
+ request, requestType);
+
+ /* Find an existing application for this request. */
+ Application application = getExistingApplication(request,
+ requestCanCreateApplication);
+
+ if (application != null) {
+ /*
+ * There is an existing application. We can use this as long as the
+ * user not specifically requested to close or restart it.
+ */
+
+ final boolean restartApplication = (getHTTPRequestParameter(
+ request, URL_PARAMETER_RESTART_APPLICATION) != null);
+ final boolean closeApplication = (getHTTPRequestParameter(request,
+ URL_PARAMETER_CLOSE_APPLICATION) != null);
+
+ if (restartApplication) {
+ closeApplication(application, request.getPortletSession(false));
+ return createApplication(request);
+ } else if (closeApplication) {
+ closeApplication(application, request.getPortletSession(false));
+ return null;
+ } else {
+ return application;
+ }
+ }
+
+ // No existing application was found
+
+ if (requestCanCreateApplication) {
+ return createApplication(request);
+ } else {
+ throw new SessionExpiredException();
+ }
+ }
+
+ private void closeApplication(Application application,
+ PortletSession session) {
+ if (application == null) {
+ return;
+ }
+
+ application.close();
+ if (session != null) {
+ PortletApplicationContext2 context = getApplicationContext(session);
+ context.removeApplication(application);
+ }
+ }
+
+ private Application createApplication(PortletRequest request)
+ throws PortletException, MalformedURLException {
+ Application newApplication = getNewApplication(request);
+ final PortletApplicationContext2 context = getApplicationContext(request
+ .getPortletSession());
+ context.addApplication(newApplication, request.getWindowID());
+ return newApplication;
+ }
+
+ private Application getExistingApplication(PortletRequest request,
+ boolean allowSessionCreation) throws MalformedURLException,
+ SessionExpiredException {
+
+ final PortletSession session = request
+ .getPortletSession(allowSessionCreation);
+
+ if (session == null) {
+ throw new SessionExpiredException();
+ }
+
+ PortletApplicationContext2 context = getApplicationContext(session);
+ Application application = context.getApplicationForWindowId(request
+ .getWindowID());
+ if (application == null) {
+ return null;
+ }
+ if (application.isRunning()) {
+ return application;
+ }
+ // application found but not running
+ context.removeApplication(application);
+
+ 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:
+ * <ul>
+ * <li>
+ * {@link #writeAjaxPageHtmlMainDiv(RenderRequest, RenderResponse, BufferedWriter, String)}
+ * <li>
+ * {@link #getVaadinConfigurationMap(RenderRequest, RenderResponse, Application, String)}
+ * <li>
+ * {@link #writeAjaxPageHtmlVaadinScripts(RenderRequest, RenderResponse, BufferedWriter, Application, String)}
+ * </ul>
+ *
+ * @param request
+ * the portlet request.
+ * @param response
+ * the portlet response to write to.
+ * @param root
+ * @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, Root root, Application application)
+ throws IOException, MalformedURLException, PortletException {
+
+ response.setContentType("text/html");
+ final BufferedWriter page = new BufferedWriter(new OutputStreamWriter(
+ response.getPortletOutputStream(), "UTF-8"));
+
+ // TODO Currently, we can only load widgetsets and themes from the
+ // portal
+
+ String themeName = getThemeForRoot(request, root);
+
+ writeAjaxPageHtmlVaadinScripts(request, response, page, application,
+ themeName);
+
+ /*- Add classnames;
+ * .v-app
+ * .v-app-loading
+ * .v-app-<simpleName for app class>
+ * .v-theme-<themeName, remove non-alphanum>
+ */
+ String appClass = "v-app-";
+ try {
+ appClass += getApplicationClass().getSimpleName();
+ } catch (ClassNotFoundException e) {
+ appClass += "unknown";
+ logger.log(Level.SEVERE, "Could not find application class", e);
+ }
+ String themeClass = "v-theme-"
+ + themeName.replaceAll("[^a-zA-Z0-9]", "");
+
+ String classNames = "v-app " + themeClass + " " + appClass;
+
+ String style = getApplicationProperty(PORTLET_PARAMETER_STYLE);
+ String divStyle = "";
+ if (style != null) {
+ divStyle = "style=\"" + style + "\"";
+ }
+
+ writeAjaxPageHtmlMainDiv(request, response, page,
+ getApplicationDomId(request), classNames, divStyle);
+
+ page.close();
+ }
+
+ /**
+ * Creates and returns a unique ID for the DIV where the application is to
+ * be rendered. We need to generate a unique ID because some portals already
+ * create a DIV with the portlet's Window ID as the DOM ID.
+ *
+ * @param request
+ * PortletRequest
+ * @return the id to use in the DOM
+ */
+ private String getApplicationDomId(PortletRequest request) {
+ return "v-" + request.getWindowID();
+ }
+
+ /**
+ * 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
+ // applications will load this exactly once
+ String portalTheme = getPortalProperty(PORTAL_PARAMETER_VAADIN_THEME,
+ request.getPortalContext());
+
+ writer.write("<script type=\"text/javascript\">\n");
+ writer.write("if(!vaadin || !vaadin.vaadinConfigurations) {\n "
+ + "if(!vaadin) { var vaadin = {}} \n"
+ + "vaadin.vaadinConfigurations = {};\n"
+ + "if (!vaadin.themesLoaded) { vaadin.themesLoaded = {}; }\n");
+ if (!isProductionMode()) {
+ writer.write("vaadin.debug = true;\n");
+ }
+
+ writeAjaxPageScriptWidgetset(request, response, writer);
+
+ Map<String, String> config = getVaadinConfigurationMap(request,
+ response, application, themeURI);
+ writeAjaxPageScriptConfigurations(request, response, writer, config);
+
+ writer.write("</script>\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('<iframe tabIndex=\"-1\" id=\"__gwt_historyFrame\" "
+ + "style=\"position:absolute;width:0;height:0;border:0;overflow:"
+ + "hidden;opacity:0;top:-100px;left:-100px;\" src=\"javascript:false\"></iframe>');\n");
+ writer.write("document.write(\"<script language='javascript' src='"
+ + widgetsetURL + "'><\\/script>\");\n}\n");
+ }
+
+ /**
+ * Returns the configuration parameters to pass to the client.
+ *
+ * To add configuration parameters for the client, override, call the super
+ * method and then modify the map. Overriding this method may also require
+ * client side changes in {@link ApplicationConnection} and
+ * {@link ApplicationConfiguration}.
+ *
+ * Note that this method must escape and quote the values when appropriate.
+ *
+ * The map returned is typically a {@link LinkedHashMap} to preserve
+ * insertion order, but it is not guaranteed to be one.
+ *
+ * @param request
+ * @param response
+ * @param application
+ * @param themeURI
+ * @return modifiable Map from parameter name to its full value
+ * @throws PortletException
+ */
+ protected Map<String, String> getVaadinConfigurationMap(
+ RenderRequest request, RenderResponse response,
+ Application application, String themeURI) throws PortletException {
+ Map<String, String> config = new LinkedHashMap<String, String>();
+
+ /*
+ * We need this in order to get uploads to work. TODO this is not needed
+ * for uploads anymore, check if this is needed for some other things
+ */
+ PortletURL appUri = response.createActionURL();
+ config.put("appUri", "'" + appUri.toString() + "'");
+ config.put("usePortletURLs", "true");
+ ResourceURL uidlUrlBase = response.createResourceURL();
+ uidlUrlBase.setResourceID("UIDL");
+ config.put("portletUidlURLBase", "'" + uidlUrlBase.toString() + "'");
+ config.put("pathInfo", "''");
+ config.put("themeUri", "'" + themeURI + "'");
+
+ String versionInfo = "{vaadinVersion:\""
+ + AbstractApplicationServlet.VERSION
+ + "\",applicationVersion:\"" + application.getVersion() + "\"}";
+ config.put("versionInfo", versionInfo);
+
+ // 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);
+ }
+ if (systemMessages != null) {
+ // Write the CommunicationError -message to client
+ String caption = systemMessages.getCommunicationErrorCaption();
+ if (caption != null) {
+ caption = "\"" + caption + "\"";
+ }
+ String message = systemMessages.getCommunicationErrorMessage();
+ if (message != null) {
+ message = "\"" + message + "\"";
+ }
+ String url = systemMessages.getCommunicationErrorURL();
+ if (url != null) {
+ url = "\"" + url + "\"";
+ }
+
+ config.put("\"comErrMsg\"", "{" + "\"caption\":" + caption + ","
+ + "\"message\" : " + message + "," + "\"url\" : " + url
+ + "}");
+
+ // Write the AuthenticationError -message to client
+ caption = systemMessages.getAuthenticationErrorCaption();
+ if (caption != null) {
+ caption = "\"" + caption + "\"";
+ }
+ message = systemMessages.getAuthenticationErrorMessage();
+ if (message != null) {
+ message = "\"" + message + "\"";
+ }
+ url = systemMessages.getAuthenticationErrorURL();
+ if (url != null) {
+ url = "\"" + url + "\"";
+ }
+
+ config.put("\"authErrMsg\"", "{" + "\"caption\":" + caption + ","
+ + "\"message\" : " + message + "," + "\"url\" : " + url
+ + "}");
+ }
+
+ return config;
+ }
+
+ /**
+ * Constructs the Vaadin configuration section for
+ * {@link ApplicationConnection} and {@link ApplicationConfiguration}.
+ *
+ * Typically this method should not be overridden. Instead, modify
+ * {@link #getVaadinConfigurationMap(RenderRequest, RenderResponse, Application, String)}
+ * .
+ *
+ * @param request
+ * @param response
+ * @param writer
+ * @param config
+ * @throws IOException
+ * @throws PortletException
+ */
+ protected void writeAjaxPageScriptConfigurations(RenderRequest request,
+ RenderResponse response, final BufferedWriter writer,
+ Map<String, String> config) throws IOException, PortletException {
+
+ writer.write("vaadin.vaadinConfigurations[\""
+ + getApplicationDomId(request) + "\"] = {");
+
+ Iterator<String> keyIt = config.keySet().iterator();
+ while (keyIt.hasNext()) {
+ String key = keyIt.next();
+ writer.write(key + ": " + config.get(key));
+ if (keyIt.hasNext()) {
+ writer.write(", ");
+ }
+ }
+
+ writer.write("};\n");
+ }
+
+ /**
+ * Writes the Vaadin theme loading section of the portlet HTML. Loads both
+ * the portal theme and the portlet theme in this order, skipping loading of
+ * themes that are already loaded (matched by name).
+ *
+ * @param request
+ * @param writer
+ * @param themeName
+ * @param themeURI
+ * @param portalTheme
+ * @throws IOException
+ */
+ protected void writeAjaxPageHtmlTheme(RenderRequest request,
+ final BufferedWriter writer, String themeName, String themeURI,
+ String portalTheme) throws IOException {
+ writer.write("<script type=\"text/javascript\">\n");
+
+ if (portalTheme == null) {
+ portalTheme = DEFAULT_THEME_NAME;
+ }
+
+ writer.write("if(!vaadin.themesLoaded['" + portalTheme + "']) {\n");
+ writer.write("var defaultStylesheet = document.createElement('link');\n");
+ writer.write("defaultStylesheet.setAttribute('rel', 'stylesheet');\n");
+ writer.write("defaultStylesheet.setAttribute('type', 'text/css');\n");
+ writer.write("defaultStylesheet.setAttribute('href', '"
+ + getThemeURI(portalTheme, request) + "/styles.css');\n");
+ writer.write("document.getElementsByTagName('head')[0].appendChild(defaultStylesheet);\n");
+ writer.write("vaadin.themesLoaded['" + portalTheme + "'] = true;\n}\n");
+
+ if (!portalTheme.equals(themeName)) {
+ writer.write("if(!vaadin.themesLoaded['" + themeName + "']) {\n");
+ writer.write("var stylesheet = document.createElement('link');\n");
+ writer.write("stylesheet.setAttribute('rel', 'stylesheet');\n");
+ writer.write("stylesheet.setAttribute('type', 'text/css');\n");
+ writer.write("stylesheet.setAttribute('href', '" + themeURI
+ + "/styles.css');\n");
+ writer.write("document.getElementsByTagName('head')[0].appendChild(stylesheet);\n");
+ writer.write("vaadin.themesLoaded['" + themeName
+ + "'] = true;\n}\n");
+ }
+
+ writer.write("</script>\n");
+ }
+
+ /**
+ * 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 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("<div id=\"" + id + "\" class=\"" + classNames + "\" "
+ + divStyle + ">");
+ writer.write("<div class=\"v-app-loading\"></div>");
+ writer.write("</div>\n");
+ writer.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 theme for given request/window
+ *
+ * @param request
+ * @param window
+ * @return
+ */
+ protected String getThemeForRoot(PortletRequest request, Root root) {
+ // Finds theme name
+ String themeName;
+
+ // theme defined for the window?
+ themeName = null;// window.getTheme();
+
+ if (themeName == null) {
+ // no, is the default theme defined by the portal?
+ themeName = getPortalProperty(
+ Constants.PORTAL_PARAMETER_VAADIN_THEME,
+ request.getPortalContext());
+ }
+
+ if (themeName == null) {
+ // no, using the default theme defined by Vaadin
+ themeName = DEFAULT_THEME_NAME;
+ }
+
+ return themeName;
+ }
+
+ protected abstract Class<? extends Application> getApplicationClass()
+ throws ClassNotFoundException;
+
+ protected Application getNewApplication(PortletRequest request)
+ throws PortletException {
+ try {
+ final Application application = getApplicationClass().newInstance();
+ return application;
+ } catch (final IllegalAccessException e) {
+ throw new PortletException("getNewApplication failed", e);
+ } catch (final InstantiationException e) {
+ throw new PortletException("getNewApplication failed", e);
+ } catch (final ClassNotFoundException e) {
+ throw new PortletException("getNewApplication failed", e);
+ }
+ }
+
+ protected ClassLoader getClassLoader() throws PortletException {
+ // TODO Add support for custom class loader
+ return getClass().getClassLoader();
+ }
+
+ /**
+ * Get system messages from the current application class
+ *
+ * @return
+ */
+ protected SystemMessages getSystemMessages() {
+ try {
+ Class<? extends Application> appCls = getApplicationClass();
+ Method m = appCls.getMethod("getSystemMessages", (Class[]) null);
+ return (Application.SystemMessages) m.invoke(null, (Object[]) null);
+ } catch (ClassNotFoundException e) {
+ // This should never happen
+ throw new SystemMessageException(e);
+ } catch (SecurityException e) {
+ throw new SystemMessageException(
+ "Application.getSystemMessage() should be static public", e);
+ } catch (NoSuchMethodException e) {
+ // This is completely ok and should be silently ignored
+ } catch (IllegalArgumentException e) {
+ // This should never happen
+ throw new SystemMessageException(e);
+ } catch (IllegalAccessException e) {
+ throw new SystemMessageException(
+ "Application.getSystemMessage() should be static public", e);
+ } catch (InvocationTargetException e) {
+ // This should never happen
+ throw new SystemMessageException(e);
+ }
+ return Application.getSystemMessages();
+ }
+
+ private void handleServiceException(PortletRequest request,
+ PortletResponse response, Application application, Throwable e)
+ throws IOException, PortletException {
+ // TODO Check that this error handler is working when running inside a
+ // portlet
+
+ // if this was an UIDL request, response UIDL back to client
+ if (getRequestType(request) == RequestType.UIDL) {
+ Application.SystemMessages ci = getSystemMessages();
+ criticalNotification(request, (ResourceResponse) response,
+ ci.getInternalErrorCaption(), ci.getInternalErrorMessage(),
+ null, ci.getInternalErrorURL());
+ if (application != null) {
+ application.getErrorHandler()
+ .terminalError(new RequestError(e));
+ } else {
+ throw new PortletException(e);
+ }
+ } else {
+ // Re-throw other exceptions
+ throw new PortletException(e);
+ }
+
+ }
+
+ @SuppressWarnings("serial")
+ public class RequestError implements Terminal.ErrorEvent, Serializable {
+
+ private final Throwable throwable;
+
+ public RequestError(Throwable throwable) {
+ this.throwable = throwable;
+ }
+
+ public Throwable getThrowable() {
+ return throwable;
+ }
+
+ }
+
+ /**
+ * Send notification to client's application. Used to notify client of
+ * critical errors and session expiration due to long inactivity. Server has
+ * no knowledge of what application client refers to.
+ *
+ * @param request
+ * the Portlet request instance.
+ * @param response
+ * the Portlet response to write to.
+ * @param caption
+ * for the notification
+ * @param message
+ * for the notification
+ * @param details
+ * a detail message to show in addition to the passed message.
+ * Currently shown directly but could be hidden behind a details
+ * drop down.
+ * @param url
+ * url to load after message, null for current page
+ * @throws IOException
+ * if the writing failed due to input/output error.
+ */
+ void criticalNotification(PortletRequest request, MimeResponse response,
+ String caption, String message, String details, String url)
+ throws IOException {
+
+ // clients JS app is still running, but server application either
+ // no longer exists or it might fail to perform reasonably.
+ // send a notification to client's application and link how
+ // to "restart" application.
+
+ if (caption != null) {
+ caption = "\"" + caption + "\"";
+ }
+ if (details != null) {
+ if (message == null) {
+ message = details;
+ } else {
+ message += "<br/><br/>" + details;
+ }
+ }
+ if (message != null) {
+ message = "\"" + message + "\"";
+ }
+ if (url != null) {
+ url = "\"" + url + "\"";
+ }
+
+ // Set the response type
+ response.setContentType("application/json; charset=UTF-8");
+ final OutputStream out = response.getPortletOutputStream();
+ final PrintWriter outWriter = new PrintWriter(new BufferedWriter(
+ new OutputStreamWriter(out, "UTF-8")));
+ outWriter.print("for(;;);[{\"changes\":[], \"meta\" : {"
+ + "\"appError\": {" + "\"caption\":" + caption + ","
+ + "\"message\" : " + message + "," + "\"url\" : " + url
+ + "}}, \"resources\": {}, \"locales\":[]}]");
+ outWriter.close();
+ }
+
+ /**
+ * 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");
+
+ // TODO test on non-LifeRay platforms
+
+ String value;
+ if (isLifeRay) {
+ value = getLifeRayPortalProperty(name);
+ } else {
+ value = context.getProperty(name);
+ }
+
+ return value;
+ }
+
+ private static String getLifeRayPortalProperty(String name) {
+ String value;
+ try {
+ value = PropsUtil.get(name);
+ } catch (Exception e) {
+ value = null;
+ }
+ return value;
+ }
+
+ /**
+ * Try to get an HTTP header value from a request using portal specific
+ * APIs.
+ *
+ * @param name
+ * HTTP header name
+ * @return the value of the header (empty string if defined without a value,
+ * null if the parameter is not present or retrieving it failed)
+ */
+ private static String getHTTPHeader(PortletRequest request, String name) {
+ String value = null;
+ String portalInfo = request.getPortalContext().getPortalInfo()
+ .toLowerCase();
+ if (portalInfo.contains("liferay")) {
+ value = getLiferayHTTPHeader(request, name);
+ } else if (portalInfo.contains("gatein")) {
+ value = getGateInHTTPHeader(request, name);
+ }
+ return value;
+ }
+
+ /**
+ * Try to get the value of a HTTP request parameter from a portlet request
+ * using portal specific APIs. It is not possible to get the HTTP request
+ * parameters using the official Portlet 2.0 API.
+ *
+ * @param name
+ * HTTP request parameter name
+ * @return the value of the parameter (empty string if parameter defined
+ * without a value, null if the parameter is not present or
+ * retrieving it failed)
+ */
+ private static String getHTTPRequestParameter(PortletRequest request,
+ String name) {
+ String value = request.getParameter(name);
+ if (value == null) {
+ String portalInfo = request.getPortalContext().getPortalInfo()
+ .toLowerCase();
+ if (portalInfo.contains("liferay")) {
+ value = getLiferayHTTPRequestParameter(request, name);
+ } else if (portalInfo.contains("gatein")) {
+ value = getGateInHTTPRequestParameter(request, name);
+ }
+ }
+ return value;
+ }
+
+ private static String getGateInHTTPRequestParameter(PortletRequest request,
+ String name) {
+ String value = null;
+ try {
+ Method getRealReq = request.getClass().getMethod("getRealRequest");
+ HttpServletRequestWrapper origRequest = (HttpServletRequestWrapper) getRealReq
+ .invoke(request);
+ value = origRequest.getParameter(name);
+ } catch (Exception e) {
+ // do nothing - not on GateIn simple-portal
+ }
+ return value;
+ }
+
+ private static String getLiferayHTTPRequestParameter(
+ PortletRequest request, String name) {
+ try {
+ // httpRequest = PortalUtil.getHttpServletRequest(request);
+ HttpServletRequest httpRequest = (HttpServletRequest) PortalClassInvoker
+ .invoke("com.liferay.portal.util.PortalUtil",
+ "getHttpServletRequest", request);
+
+ // httpRequest =
+ // PortalUtil.getOriginalServletRequest(httpRequest);
+ httpRequest = (HttpServletRequest) PortalClassInvoker.invoke(
+ "com.liferay.portal.util.PortalUtil",
+ "getOriginalServletRequest", httpRequest);
+ if (httpRequest != null) {
+ return httpRequest.getParameter(name);
+ }
+ } catch (Exception e) {
+ // ignore and return null - unable to get the original request
+ }
+ return null;
+ }
+
+ private static String getGateInHTTPHeader(PortletRequest request,
+ String name) {
+ String value = null;
+ try {
+ Method getRealReq = request.getClass().getMethod("getRealRequest");
+ HttpServletRequestWrapper origRequest = (HttpServletRequestWrapper) getRealReq
+ .invoke(request);
+ value = origRequest.getHeader(name);
+ } catch (Exception e) {
+ // do nothing - not on GateIn simple-portal
+ }
+ return value;
+ }
+
+ private static String getLiferayHTTPHeader(PortletRequest request,
+ String name) {
+ try {
+ // httpRequest = PortalUtil.getHttpServletRequest(request);
+ HttpServletRequest httpRequest = (HttpServletRequest) PortalClassInvoker
+ .invoke("com.liferay.portal.util.PortalUtil",
+ "getHttpServletRequest", request);
+
+ // httpRequest =
+ // PortalUtil.getOriginalServletRequest(httpRequest);
+ httpRequest = (HttpServletRequest) PortalClassInvoker.invoke(
+ "com.liferay.portal.util.PortalUtil",
+ "getOriginalServletRequest", httpRequest);
+ if (httpRequest != null) {
+ return httpRequest.getHeader(name);
+ }
+ } catch (Exception e) {
+ // ignore and return null - unable to get the original request
+ }
+ return null;
+ }
+
+ /**
+ *
+ * Gets the application context for a PortletSession. If no context is
+ * currently stored in a session a new context is created and stored in the
+ * session.
+ *
+ * @param portletSession
+ * the portlet session.
+ * @return the application context for the session.
+ */
+ protected PortletApplicationContext2 getApplicationContext(
+ PortletSession portletSession) {
+ return PortletApplicationContext2.getApplicationContext(portletSession);
+ }
+
+}
diff --git a/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java b/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java
index eed6c4edc3..96d586ef71 100644
--- a/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java
+++ b/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java
@@ -2223,7 +2223,7 @@ public abstract class AbstractCommunicationManager implements
* @see com.vaadin.terminal.URIHandler
*/
@SuppressWarnings("deprecation")
- protected DownloadStream handleURI(Window window, Request request,
+ protected DownloadStream handleURI(Root root, Request request,
Response response, Callback callback) {
String uri = callback.getRequestPathInfo(request);
diff --git a/src/com/vaadin/terminal/gwt/server/ApplicationPortlet.java b/src/com/vaadin/terminal/gwt/server/ApplicationPortlet.java
index ef646a0748..2623807b59 100644
--- a/src/com/vaadin/terminal/gwt/server/ApplicationPortlet.java
+++ b/src/com/vaadin/terminal/gwt/server/ApplicationPortlet.java
@@ -1,250 +1,250 @@
/*
@ITMillApache2LicenseForJavaFiles@
*/
-//package com.vaadin.terminal.gwt.server;
-//
-//import java.io.IOException;
-//import java.io.OutputStream;
-//import java.io.PrintWriter;
-//import java.io.Serializable;
-//import java.util.logging.Level;
-//import java.util.logging.Logger;
-//
-//import javax.portlet.ActionRequest;
-//import javax.portlet.ActionResponse;
-//import javax.portlet.PortalContext;
-//import javax.portlet.Portlet;
-//import javax.portlet.PortletConfig;
-//import javax.portlet.PortletException;
-//import javax.portlet.PortletRequestDispatcher;
-//import javax.portlet.PortletSession;
-//import javax.portlet.RenderRequest;
-//import javax.portlet.RenderResponse;
-//
-//import com.liferay.portal.kernel.util.PropsUtil;
-//import com.vaadin.Application;
-//
-///**
-// * Portlet main class for Portlet 1.0 (JSR-168) portlets which consist of a
-// * portlet and a servlet. For Portlet 2.0 (JSR-286, no servlet required), use
-// * {@link ApplicationPortlet2} instead.
-// */
-//@SuppressWarnings("serial")
-//public class ApplicationPortlet implements Portlet, Serializable {
-// // portlet configuration parameters
-// private static final String PORTLET_PARAMETER_APPLICATION = "application";
-// private static final String PORTLET_PARAMETER_STYLE = "style";
-// private static final String PORTLET_PARAMETER_WIDGETSET = "widgetset";
-//
-// // The application to show
-// protected String app = null;
-// // some applications might require forced height (and, more seldom, width)
-// protected String style = null; // e.g "height:500px;"
-// // force the portlet to use this widgetset - portlet level setting
-// protected String portletWidgetset = null;
-//
-// public void destroy() {
-//
-// }
-//
-// public void init(PortletConfig config) throws PortletException {
-// app = config.getInitParameter(PORTLET_PARAMETER_APPLICATION);
-// if (app == null) {
-// throw new PortletException(
-// "No porlet application url defined in portlet.xml. Define the '"
-// + PORTLET_PARAMETER_APPLICATION
-// + "' init parameter to be the servlet deployment path.");
-// }
-// style = config.getInitParameter(PORTLET_PARAMETER_STYLE);
-// // enable forcing the selection of the widgetset in portlet
-// // configuration for a single portlet (backwards compatibility)
-// portletWidgetset = config.getInitParameter(PORTLET_PARAMETER_WIDGETSET);
-// }
-//
-// public void processAction(ActionRequest request, ActionResponse response)
-// throws PortletException, IOException {
-// PortletApplicationContext.dispatchRequest(this, request, response);
-// }
-//
-// public void render(RenderRequest request, RenderResponse response)
-// throws PortletException, IOException {
-//
-// // display the Vaadin application
-// writeAjaxWindow(request, response);
-// }
-//
-// protected void writeAjaxWindow(RenderRequest request,
-// RenderResponse response) throws IOException {
-//
-// response.setContentType("text/html");
-// if (app != null) {
-// PortletSession sess = request.getPortletSession();
-// PortletApplicationContext ctx = PortletApplicationContext
-// .getApplicationContext(sess);
-//
-// PortletRequestDispatcher dispatcher = sess.getPortletContext()
-// .getRequestDispatcher("/" + app);
-//
-// try {
-// // portal-wide settings
-// PortalContext portalCtx = request.getPortalContext();
-//
-// boolean isLifeRay = portalCtx.getPortalInfo().toLowerCase()
-// .contains("liferay");
-//
-// request.setAttribute(ApplicationServlet.REQUEST_FRAGMENT,
-// "true");
-//
-// // fixed base theme to use - all portal pages with Vaadin
-// // applications will load this exactly once
-// String portalTheme = getPortalProperty(
-// Constants.PORTAL_PARAMETER_VAADIN_THEME, portalCtx);
-//
-// String portalWidgetset = getPortalProperty(
-// Constants.PORTAL_PARAMETER_VAADIN_WIDGETSET, portalCtx);
-//
-// // location of the widgetset(s) and default theme (to which
-// // /VAADIN/widgetsets/...
-// // is appended)
-// String portalResourcePath = getPortalProperty(
-// Constants.PORTAL_PARAMETER_VAADIN_RESOURCE_PATH,
-// portalCtx);
-//
-// if (portalResourcePath != null) {
-// // if portalResourcePath is defined, set it as a request
-// // parameter which will override the default location in
-// // servlet
-// request.setAttribute(
-// ApplicationServlet.REQUEST_VAADIN_STATIC_FILE_PATH,
-// portalResourcePath);
-// }
-//
-// // - if the user has specified a widgetset for this portlet, use
-// // it from the portlet (not fully supported)
-// // - otherwise, if specified, use the portal-wide widgetset
-// // and widgetset path settings (recommended)
-// // - finally, default to use the default widgetset if nothing
-// // else is found
-// if (portletWidgetset != null) {
-// request.setAttribute(ApplicationServlet.REQUEST_WIDGETSET,
-// portletWidgetset);
-// }
-// if (portalWidgetset != null) {
-// request.setAttribute(
-// ApplicationServlet.REQUEST_SHARED_WIDGETSET,
-// portalWidgetset);
-// }
-//
-// if (style != null) {
-// request.setAttribute(ApplicationServlet.REQUEST_APPSTYLE,
-// style);
-// }
-//
-// // portalTheme is only used if the shared portal resource
-// // directory is defined
-// if (portalTheme != null && portalResourcePath != null) {
-// request.setAttribute(
-// ApplicationServlet.REQUEST_DEFAULT_THEME,
-// portalTheme);
-//
-// String defaultThemeUri = null;
-// defaultThemeUri = portalResourcePath + "/"
-// + AbstractApplicationServlet.THEME_DIRECTORY_PATH
-// + portalTheme;
-// /*
-// * Make sure portal default Vaadin theme is included in DOM.
-// * Vaadin portlet themes do not "inherit" base theme, so we
-// * need to force loading of the common base theme.
-// */
-// OutputStream out = response.getPortletOutputStream();
-//
-// // Using portal-wide theme
-// String loadDefaultTheme = ("<script type=\"text/javascript\">\n"
-// + "if(!vaadin) { var vaadin = {} } \n"
-// + "if(!vaadin.themesLoaded) { vaadin.themesLoaded = {} } \n"
-// + "if(!vaadin.themesLoaded['"
-// + portalTheme
-// + "']) {\n"
-// + "var stylesheet = document.createElement('link');\n"
-// + "stylesheet.setAttribute('rel', 'stylesheet');\n"
-// + "stylesheet.setAttribute('type', 'text/css');\n"
-// + "stylesheet.setAttribute('href', '"
-// + defaultThemeUri
-// + "/styles.css');\n"
-// + "document.getElementsByTagName('head')[0].appendChild(stylesheet);\n"
-// + "vaadin.themesLoaded['"
-// + portalTheme
-// + "'] = true;\n}\n" + "</script>\n");
-// out.write(loadDefaultTheme.getBytes());
-// }
-//
-// dispatcher.include(request, response);
-//
-// if (isLifeRay) {
-// /*
-// * Temporary support to heartbeat Liferay session when using
-// * Vaadin based portlet. We hit an extra xhr to liferay
-// * servlet to extend the session lifetime after each Vaadin
-// * request. This hack can be removed when supporting portlet
-// * 2.0 and resourceRequests.
-// *
-// * TODO make this configurable, this is not necessary with
-// * some custom session configurations.
-// */
-// OutputStream out = response.getPortletOutputStream();
-//
-// String lifeRaySessionHearbeatHack = ("<script type=\"text/javascript\">"
-// + "if(!vaadin.postRequestHooks) {"
-// + " vaadin.postRequestHooks = {};"
-// + "}"
-// + "vaadin.postRequestHooks.liferaySessionHeartBeat = function() {"
-// + " if (Liferay && Liferay.Session && Liferay.Session.setCookie) {"
-// + " Liferay.Session.setCookie();"
-// + " }"
-// + "};" + "</script>");
-// out.write(lifeRaySessionHearbeatHack.getBytes());
-// }
-//
-// } catch (PortletException e) {
-// PrintWriter out = response.getWriter();
-// out.print("<h1>Servlet include failed!</h1>");
-// Logger.getLogger(AbstractApplicationPortlet.class.getName())
-// .log(Level.WARNING, "Servlet include failed", e);
-// ctx.setPortletApplication(this, null);
-// return;
-// }
-//
-// Application app = (Application) request
-// .getAttribute(Application.class.getName());
-// ctx.setPortletApplication(this, app);
-// ctx.firePortletRenderRequest(this, request, response);
-//
-// }
-// }
-//
-// private String getPortalProperty(String name, PortalContext context) {
-// boolean isLifeRay = context.getPortalInfo().toLowerCase()
-// .contains("liferay");
-//
-// // TODO test on non-LifeRay platforms
-//
-// String value;
-// if (isLifeRay) {
-// value = getLifeRayPortalProperty(name);
-// } else {
-// value = context.getProperty(name);
-// }
-//
-// return value;
-// }
-//
-// private String getLifeRayPortalProperty(String name) {
-// String value;
-// try {
-// value = PropsUtil.get(name);
-// } catch (Exception e) {
-// value = null;
-// }
-// return value;
-// }
-// }
+package com.vaadin.terminal.gwt.server;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.Serializable;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.portlet.ActionRequest;
+import javax.portlet.ActionResponse;
+import javax.portlet.PortalContext;
+import javax.portlet.Portlet;
+import javax.portlet.PortletConfig;
+import javax.portlet.PortletException;
+import javax.portlet.PortletRequestDispatcher;
+import javax.portlet.PortletSession;
+import javax.portlet.RenderRequest;
+import javax.portlet.RenderResponse;
+
+import com.liferay.portal.kernel.util.PropsUtil;
+import com.vaadin.Application;
+
+/**
+ * Portlet main class for Portlet 1.0 (JSR-168) portlets which consist of a
+ * portlet and a servlet. For Portlet 2.0 (JSR-286, no servlet required), use
+ * {@link ApplicationPortlet2} instead.
+ */
+@SuppressWarnings("serial")
+public class ApplicationPortlet implements Portlet, Serializable {
+ // portlet configuration parameters
+ private static final String PORTLET_PARAMETER_APPLICATION = "application";
+ private static final String PORTLET_PARAMETER_STYLE = "style";
+ private static final String PORTLET_PARAMETER_WIDGETSET = "widgetset";
+
+ // The application to show
+ protected String app = null;
+ // some applications might require forced height (and, more seldom, width)
+ protected String style = null; // e.g "height:500px;"
+ // force the portlet to use this widgetset - portlet level setting
+ protected String portletWidgetset = null;
+
+ public void destroy() {
+
+ }
+
+ public void init(PortletConfig config) throws PortletException {
+ app = config.getInitParameter(PORTLET_PARAMETER_APPLICATION);
+ if (app == null) {
+ throw new PortletException(
+ "No porlet application url defined in portlet.xml. Define the '"
+ + PORTLET_PARAMETER_APPLICATION
+ + "' init parameter to be the servlet deployment path.");
+ }
+ style = config.getInitParameter(PORTLET_PARAMETER_STYLE);
+ // enable forcing the selection of the widgetset in portlet
+ // configuration for a single portlet (backwards compatibility)
+ portletWidgetset = config.getInitParameter(PORTLET_PARAMETER_WIDGETSET);
+ }
+
+ public void processAction(ActionRequest request, ActionResponse response)
+ throws PortletException, IOException {
+ PortletApplicationContext.dispatchRequest(this, request, response);
+ }
+
+ public void render(RenderRequest request, RenderResponse response)
+ throws PortletException, IOException {
+
+ // display the Vaadin application
+ writeAjaxWindow(request, response);
+ }
+
+ protected void writeAjaxWindow(RenderRequest request,
+ RenderResponse response) throws IOException {
+
+ response.setContentType("text/html");
+ if (app != null) {
+ PortletSession sess = request.getPortletSession();
+ PortletApplicationContext ctx = PortletApplicationContext
+ .getApplicationContext(sess);
+
+ PortletRequestDispatcher dispatcher = sess.getPortletContext()
+ .getRequestDispatcher("/" + app);
+
+ try {
+ // portal-wide settings
+ PortalContext portalCtx = request.getPortalContext();
+
+ boolean isLifeRay = portalCtx.getPortalInfo().toLowerCase()
+ .contains("liferay");
+
+ request.setAttribute(ApplicationServlet.REQUEST_FRAGMENT,
+ "true");
+
+ // fixed base theme to use - all portal pages with Vaadin
+ // applications will load this exactly once
+ String portalTheme = getPortalProperty(
+ Constants.PORTAL_PARAMETER_VAADIN_THEME, portalCtx);
+
+ String portalWidgetset = getPortalProperty(
+ Constants.PORTAL_PARAMETER_VAADIN_WIDGETSET, portalCtx);
+
+ // location of the widgetset(s) and default theme (to which
+ // /VAADIN/widgetsets/...
+ // is appended)
+ String portalResourcePath = getPortalProperty(
+ Constants.PORTAL_PARAMETER_VAADIN_RESOURCE_PATH,
+ portalCtx);
+
+ if (portalResourcePath != null) {
+ // if portalResourcePath is defined, set it as a request
+ // parameter which will override the default location in
+ // servlet
+ request.setAttribute(
+ ApplicationServlet.REQUEST_VAADIN_STATIC_FILE_PATH,
+ portalResourcePath);
+ }
+
+ // - if the user has specified a widgetset for this portlet, use
+ // it from the portlet (not fully supported)
+ // - otherwise, if specified, use the portal-wide widgetset
+ // and widgetset path settings (recommended)
+ // - finally, default to use the default widgetset if nothing
+ // else is found
+ if (portletWidgetset != null) {
+ request.setAttribute(ApplicationServlet.REQUEST_WIDGETSET,
+ portletWidgetset);
+ }
+ if (portalWidgetset != null) {
+ request.setAttribute(
+ ApplicationServlet.REQUEST_SHARED_WIDGETSET,
+ portalWidgetset);
+ }
+
+ if (style != null) {
+ request.setAttribute(ApplicationServlet.REQUEST_APPSTYLE,
+ style);
+ }
+
+ // portalTheme is only used if the shared portal resource
+ // directory is defined
+ if (portalTheme != null && portalResourcePath != null) {
+ request.setAttribute(
+ ApplicationServlet.REQUEST_DEFAULT_THEME,
+ portalTheme);
+
+ String defaultThemeUri = null;
+ defaultThemeUri = portalResourcePath + "/"
+ + AbstractApplicationServlet.THEME_DIRECTORY_PATH
+ + portalTheme;
+ /*
+ * Make sure portal default Vaadin theme is included in DOM.
+ * Vaadin portlet themes do not "inherit" base theme, so we
+ * need to force loading of the common base theme.
+ */
+ OutputStream out = response.getPortletOutputStream();
+
+ // Using portal-wide theme
+ String loadDefaultTheme = ("<script type=\"text/javascript\">\n"
+ + "if(!vaadin) { var vaadin = {} } \n"
+ + "if(!vaadin.themesLoaded) { vaadin.themesLoaded = {} } \n"
+ + "if(!vaadin.themesLoaded['"
+ + portalTheme
+ + "']) {\n"
+ + "var stylesheet = document.createElement('link');\n"
+ + "stylesheet.setAttribute('rel', 'stylesheet');\n"
+ + "stylesheet.setAttribute('type', 'text/css');\n"
+ + "stylesheet.setAttribute('href', '"
+ + defaultThemeUri
+ + "/styles.css');\n"
+ + "document.getElementsByTagName('head')[0].appendChild(stylesheet);\n"
+ + "vaadin.themesLoaded['"
+ + portalTheme
+ + "'] = true;\n}\n" + "</script>\n");
+ out.write(loadDefaultTheme.getBytes());
+ }
+
+ dispatcher.include(request, response);
+
+ if (isLifeRay) {
+ /*
+ * Temporary support to heartbeat Liferay session when using
+ * Vaadin based portlet. We hit an extra xhr to liferay
+ * servlet to extend the session lifetime after each Vaadin
+ * request. This hack can be removed when supporting portlet
+ * 2.0 and resourceRequests.
+ *
+ * TODO make this configurable, this is not necessary with
+ * some custom session configurations.
+ */
+ OutputStream out = response.getPortletOutputStream();
+
+ String lifeRaySessionHearbeatHack = ("<script type=\"text/javascript\">"
+ + "if(!vaadin.postRequestHooks) {"
+ + " vaadin.postRequestHooks = {};"
+ + "}"
+ + "vaadin.postRequestHooks.liferaySessionHeartBeat = function() {"
+ + " if (Liferay && Liferay.Session && Liferay.Session.setCookie) {"
+ + " Liferay.Session.setCookie();"
+ + " }"
+ + "};" + "</script>");
+ out.write(lifeRaySessionHearbeatHack.getBytes());
+ }
+
+ } catch (PortletException e) {
+ PrintWriter out = response.getWriter();
+ out.print("<h1>Servlet include failed!</h1>");
+ Logger.getLogger(AbstractApplicationPortlet.class.getName())
+ .log(Level.WARNING, "Servlet include failed", e);
+ ctx.setPortletApplication(this, null);
+ return;
+ }
+
+ Application app = (Application) request
+ .getAttribute(Application.class.getName());
+ ctx.setPortletApplication(this, app);
+ ctx.firePortletRenderRequest(this, request, response);
+
+ }
+ }
+
+ private String getPortalProperty(String name, PortalContext context) {
+ boolean isLifeRay = context.getPortalInfo().toLowerCase()
+ .contains("liferay");
+
+ // TODO test on non-LifeRay platforms
+
+ String value;
+ if (isLifeRay) {
+ value = getLifeRayPortalProperty(name);
+ } else {
+ value = context.getProperty(name);
+ }
+
+ return value;
+ }
+
+ private String getLifeRayPortalProperty(String name) {
+ String value;
+ try {
+ value = PropsUtil.get(name);
+ } catch (Exception e) {
+ value = null;
+ }
+ return value;
+ }
+}
diff --git a/src/com/vaadin/terminal/gwt/server/ApplicationPortlet2.java b/src/com/vaadin/terminal/gwt/server/ApplicationPortlet2.java
index 70baba5eb2..ec373908f7 100644
--- a/src/com/vaadin/terminal/gwt/server/ApplicationPortlet2.java
+++ b/src/com/vaadin/terminal/gwt/server/ApplicationPortlet2.java
@@ -1,46 +1,46 @@
/*
@ITMillApache2LicenseForJavaFiles@
*/
-//
-//package com.vaadin.terminal.gwt.server;
-//
-//import javax.portlet.PortletConfig;
-//import javax.portlet.PortletException;
-//
-//import com.vaadin.Application;
-//
-///**
-// * TODO Write documentation, fix JavaDoc tags.
-// *
-// * @author peholmst
-// */
-//public class ApplicationPortlet2 extends AbstractApplicationPortlet {
-//
-// private Class<? extends Application> applicationClass;
-//
-// @SuppressWarnings("unchecked")
-// @Override
-// public void init(PortletConfig config) throws PortletException {
-// super.init(config);
-// final String applicationClassName = config
-// .getInitParameter("application");
-// if (applicationClassName == null) {
-// throw new PortletException(
-// "Application not specified in portlet parameters");
-// }
-//
-// try {
-// applicationClass = (Class<? extends Application>) getClassLoader()
-// .loadClass(applicationClassName);
-// } catch (final ClassNotFoundException e) {
-// throw new PortletException("Failed to load application class: "
-// + applicationClassName);
-// }
-// }
-//
-// @Override
-// protected Class<? extends Application> getApplicationClass() {
-// return applicationClass;
-// }
-//
-// }
+
+package com.vaadin.terminal.gwt.server;
+
+import javax.portlet.PortletConfig;
+import javax.portlet.PortletException;
+
+import com.vaadin.Application;
+
+/**
+ * TODO Write documentation, fix JavaDoc tags.
+ *
+ * @author peholmst
+ */
+public class ApplicationPortlet2 extends AbstractApplicationPortlet {
+
+ private Class<? extends Application> applicationClass;
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public void init(PortletConfig config) throws PortletException {
+ super.init(config);
+ final String applicationClassName = config
+ .getInitParameter("application");
+ if (applicationClassName == null) {
+ throw new PortletException(
+ "Application not specified in portlet parameters");
+ }
+
+ try {
+ applicationClass = (Class<? extends Application>) getClassLoader()
+ .loadClass(applicationClassName);
+ } catch (final ClassNotFoundException e) {
+ throw new PortletException("Failed to load application class: "
+ + applicationClassName);
+ }
+ }
+
+ @Override
+ protected Class<? extends Application> getApplicationClass() {
+ return applicationClass;
+ }
+
+}
diff --git a/src/com/vaadin/terminal/gwt/server/CommunicationManager.java b/src/com/vaadin/terminal/gwt/server/CommunicationManager.java
index 14cccc618a..daeb31073f 100644
--- a/src/com/vaadin/terminal/gwt/server/CommunicationManager.java
+++ b/src/com/vaadin/terminal/gwt/server/CommunicationManager.java
@@ -284,8 +284,7 @@ public class CommunicationManager extends AbstractCommunicationManager {
InvalidUIDLSecurityKeyException {
doHandleUidlRequest(new HttpServletRequestWrapper(request),
new HttpServletResponseWrapper(response),
- new AbstractApplicationServletWrapper(applicationServlet),
- root);
+ new AbstractApplicationServletWrapper(applicationServlet), root);
}
/**
@@ -324,16 +323,16 @@ public class CommunicationManager extends AbstractCommunicationManager {
* @see AbstractCommunicationManager#handleURI(Window, Request, Response,
* Callback)
*
- * @param window
+ * @param root
* @param request
* @param response
* @param applicationServlet
* @return
*/
- DownloadStream handleURI(Window window, HttpServletRequest request,
+ DownloadStream handleURI(Root root, HttpServletRequest request,
HttpServletResponse response,
AbstractApplicationServlet applicationServlet) {
- return handleURI(window, new HttpServletRequestWrapper(request),
+ return handleURI(root, new HttpServletRequestWrapper(request),
new HttpServletResponseWrapper(response),
new AbstractApplicationServletWrapper(applicationServlet));
}
diff --git a/src/com/vaadin/terminal/gwt/server/PortletApplicationContext2.java b/src/com/vaadin/terminal/gwt/server/PortletApplicationContext2.java
index df9adc7d0b..fc281d90f9 100644
--- a/src/com/vaadin/terminal/gwt/server/PortletApplicationContext2.java
+++ b/src/com/vaadin/terminal/gwt/server/PortletApplicationContext2.java
@@ -1,418 +1,422 @@
/*
@ITMillApache2LicenseForJavaFiles@
*/
-//package com.vaadin.terminal.gwt.server;
-//
-//import java.io.File;
-//import java.io.Serializable;
-//import java.net.URL;
-//import java.util.HashMap;
-//import java.util.LinkedHashSet;
-//import java.util.Map;
-//import java.util.Set;
-//import java.util.logging.Level;
-//import java.util.logging.Logger;
-//
-//import javax.portlet.ActionRequest;
-//import javax.portlet.ActionResponse;
-//import javax.portlet.EventRequest;
-//import javax.portlet.EventResponse;
-//import javax.portlet.MimeResponse;
-//import javax.portlet.PortletConfig;
-//import javax.portlet.PortletMode;
-//import javax.portlet.PortletModeException;
-//import javax.portlet.PortletResponse;
-//import javax.portlet.PortletSession;
-//import javax.portlet.PortletURL;
-//import javax.portlet.RenderRequest;
-//import javax.portlet.RenderResponse;
-//import javax.portlet.ResourceRequest;
-//import javax.portlet.ResourceResponse;
-//import javax.portlet.ResourceURL;
-//import javax.portlet.StateAwareResponse;
-//import javax.servlet.http.HttpSessionBindingListener;
-//import javax.xml.namespace.QName;
-//
-//import com.vaadin.Application;
-//import com.vaadin.terminal.ApplicationResource;
-//import com.vaadin.terminal.ExternalResource;
-//import com.vaadin.ui.Window;
-//
-///**
-// * TODO Write documentation, fix JavaDoc tags.
-// *
-// * This is automatically registered as a {@link HttpSessionBindingListener} when
-// * {@link PortletSession#setAttribute()} is called with the context as value.
-// *
-// * @author peholmst
-// */
-//@SuppressWarnings("serial")
-//public class PortletApplicationContext2 extends AbstractWebApplicationContext {
-//
-// private static final Logger logger = Logger
-// .getLogger(PortletApplicationContext2.class.getName());
-//
-// protected Map<Application, Set<PortletListener>> portletListeners = new HashMap<Application, Set<PortletListener>>();
-//
-// protected transient PortletSession session;
-// protected transient PortletConfig portletConfig;
-//
-// protected HashMap<String, Application> portletWindowIdToApplicationMap = new HashMap<String, Application>();
-//
-// private transient PortletResponse response;
-//
-// private final Map<String, QName> eventActionDestinationMap = new HashMap<String, QName>();
-// private final Map<String, Serializable> eventActionValueMap = new HashMap<String, Serializable>();
-//
-// private final Map<String, String> sharedParameterActionNameMap = new HashMap<String, String>();
-// private final Map<String, String> sharedParameterActionValueMap = new HashMap<String, String>();
-//
-// public File getBaseDirectory() {
-// String resultPath = session.getPortletContext().getRealPath("/");
-// if (resultPath != null) {
-// return new File(resultPath);
-// } else {
-// try {
-// final URL url = session.getPortletContext().getResource("/");
-// return new File(url.getFile());
-// } catch (final Exception e) {
-// // FIXME: Handle exception
-// logger.log(
-// Level.INFO,
-// "Cannot access base directory, possible security issue "
-// + "with Application Server or Servlet Container",
-// e);
-// }
-// }
-// return null;
-// }
-//
-// protected PortletCommunicationManager getApplicationManager(
-// Application application) {
-// PortletCommunicationManager mgr = (PortletCommunicationManager) applicationToAjaxAppMgrMap
-// .get(application);
-//
-// if (mgr == null) {
-// // Creates a new manager
-// mgr = createPortletCommunicationManager(application);
-// applicationToAjaxAppMgrMap.put(application, mgr);
-// }
-// return mgr;
-// }
-//
-// protected PortletCommunicationManager createPortletCommunicationManager(
-// Application application) {
-// return new PortletCommunicationManager(application);
-// }
-//
-// public static PortletApplicationContext2 getApplicationContext(
-// PortletSession session) {
-// Object cxattr = session.getAttribute(PortletApplicationContext2.class
-// .getName());
-// PortletApplicationContext2 cx = null;
-// // can be false also e.g. if old context comes from another
-// // classloader when using
-// // <private-session-attributes>false</private-session-attributes>
-// // and redeploying the portlet - see #7461
-// if (cxattr instanceof PortletApplicationContext2) {
-// cx = (PortletApplicationContext2) cxattr;
-// }
-// if (cx == null) {
-// cx = new PortletApplicationContext2();
-// session.setAttribute(PortletApplicationContext2.class.getName(), cx);
-// }
-// if (cx.session == null) {
-// cx.session = session;
-// }
-// return cx;
-// }
-//
-// @Override
-// protected void removeApplication(Application application) {
-// super.removeApplication(application);
-// // values() is backed by map, removes the key-value pair from the map
-// portletWindowIdToApplicationMap.values().remove(application);
-// }
-//
-// protected void addApplication(Application application,
-// String portletWindowId) {
-// applications.add(application);
-// portletWindowIdToApplicationMap.put(portletWindowId, application);
-// }
-//
-// public Application getApplicationForWindowId(String portletWindowId) {
-// return portletWindowIdToApplicationMap.get(portletWindowId);
-// }
-//
-// public PortletSession getPortletSession() {
-// return session;
-// }
-//
-// public PortletConfig getPortletConfig() {
-// return portletConfig;
-// }
-//
-// public void setPortletConfig(PortletConfig config) {
-// portletConfig = config;
-// }
-//
-// public void addPortletListener(Application app, PortletListener listener) {
-// Set<PortletListener> l = portletListeners.get(app);
-// if (l == null) {
-// l = new LinkedHashSet<PortletListener>();
-// portletListeners.put(app, l);
-// }
-// l.add(listener);
-// }
-//
-// public void removePortletListener(Application app, PortletListener listener) {
-// Set<PortletListener> l = portletListeners.get(app);
-// if (l != null) {
-// l.remove(listener);
-// }
-// }
-//
-// public void firePortletRenderRequest(Application app, Window window,
-// RenderRequest request, RenderResponse response) {
-// Set<PortletListener> listeners = portletListeners.get(app);
-// if (listeners != null) {
-// for (PortletListener l : listeners) {
-// l.handleRenderRequest(request, new RestrictedRenderResponse(
-// response), window);
-// }
-// }
-// }
-//
-// public void firePortletActionRequest(Application app, Window window,
-// ActionRequest request, ActionResponse response) {
-// String key = request.getParameter(ActionRequest.ACTION_NAME);
-// if (eventActionDestinationMap.containsKey(key)) {
-// // this action request is only to send queued portlet events
-// response.setEvent(eventActionDestinationMap.get(key),
-// eventActionValueMap.get(key));
-// // cleanup
-// eventActionDestinationMap.remove(key);
-// eventActionValueMap.remove(key);
-// } else if (sharedParameterActionNameMap.containsKey(key)) {
-// // this action request is only to set shared render parameters
-// response.setRenderParameter(sharedParameterActionNameMap.get(key),
-// sharedParameterActionValueMap.get(key));
-// // cleanup
-// sharedParameterActionNameMap.remove(key);
-// sharedParameterActionValueMap.remove(key);
-// } else {
-// // normal action request, notify listeners
-// Set<PortletListener> listeners = portletListeners.get(app);
-// if (listeners != null) {
-// for (PortletListener l : listeners) {
-// l.handleActionRequest(request, response, window);
-// }
-// }
-// }
-// }
-//
-// public void firePortletEventRequest(Application app, Window window,
-// EventRequest request, EventResponse response) {
-// Set<PortletListener> listeners = portletListeners.get(app);
-// if (listeners != null) {
-// for (PortletListener l : listeners) {
-// l.handleEventRequest(request, response, window);
-// }
-// }
-// }
-//
-// public void firePortletResourceRequest(Application app, Window window,
-// ResourceRequest request, ResourceResponse response) {
-// Set<PortletListener> listeners = portletListeners.get(app);
-// if (listeners != null) {
-// for (PortletListener l : listeners) {
-// l.handleResourceRequest(request, response, window);
-// }
-// }
-// }
-//
-// public interface PortletListener extends Serializable {
-//
-// public void handleRenderRequest(RenderRequest request,
-// RenderResponse response, Window window);
-//
-// public void handleActionRequest(ActionRequest request,
-// ActionResponse response, Window window);
-//
-// public void handleEventRequest(EventRequest request,
-// EventResponse response, Window window);
-//
-// public void handleResourceRequest(ResourceRequest request,
-// ResourceResponse response, Window window);
-// }
-//
-// /**
-// * This is for use by {@link AbstractApplicationPortlet} only.
-// *
-// * TODO cleaner implementation, now "semi-static"!
-// *
-// * @param mimeResponse
-// */
-// void setResponse(PortletResponse response) {
-// this.response = response;
-// }
-//
-// @Override
-// public String generateApplicationResourceURL(ApplicationResource resource,
-// String mapKey) {
-// if (response instanceof MimeResponse) {
-// ResourceURL resourceURL = ((MimeResponse) response)
-// .createResourceURL();
-// final String filename = resource.getFilename();
-// if (filename == null) {
-// resourceURL.setResourceID("APP/" + mapKey + "/");
-// } else {
-// resourceURL.setResourceID("APP/" + mapKey + "/"
-// + urlEncode(filename));
-// }
-// return resourceURL.toString();
-// } else {
-// // in a background thread or otherwise outside a request
-// // TODO exception ??
-// return null;
-// }
-// }
-//
-// /**
-// * Creates a new action URL.
-// *
-// * @param action
-// * @return action URL or null if called outside a MimeRequest (outside a
-// * UIDL request or similar)
-// */
-// public PortletURL generateActionURL(String action) {
-// PortletURL url = null;
-// if (response instanceof MimeResponse) {
-// url = ((MimeResponse) response).createActionURL();
-// url.setParameter("javax.portlet.action", action);
-// } else {
-// return null;
-// }
-// return url;
-// }
-//
-// /**
-// * Sends a portlet event to the indicated destination.
-// *
-// * Internally, an action may be created and opened, as an event cannot be
-// * sent directly from all types of requests.
-// *
-// * The event destinations and values need to be kept in the context until
-// * sent. Any memory leaks if the action fails are limited to the session.
-// *
-// * Event names for events sent and received by a portlet need to be declared
-// * in portlet.xml .
-// *
-// * @param window
-// * a window in which a temporary action URL can be opened if
-// * necessary
-// * @param name
-// * event name
-// * @param value
-// * event value object that is Serializable and, if appropriate,
-// * has a valid JAXB annotation
-// */
-// public void sendPortletEvent(Window window, QName name, Serializable value)
-// throws IllegalStateException {
-// if (response instanceof MimeResponse) {
-// String actionKey = "" + System.currentTimeMillis();
-// while (eventActionDestinationMap.containsKey(actionKey)) {
-// actionKey = actionKey + ".";
-// }
-// PortletURL actionUrl = generateActionURL(actionKey);
-// if (actionUrl != null) {
-// eventActionDestinationMap.put(actionKey, name);
-// eventActionValueMap.put(actionKey, value);
-// window.open(new ExternalResource(actionUrl.toString()));
-// } else {
-// // this should never happen as we already know the response is a
-// // MimeResponse
-// throw new IllegalStateException(
-// "Portlet events can only be sent from a portlet request");
-// }
-// } else if (response instanceof StateAwareResponse) {
-// ((StateAwareResponse) response).setEvent(name, value);
-// } else {
-// throw new IllegalStateException(
-// "Portlet events can only be sent from a portlet request");
-// }
-// }
-//
-// /**
-// * Sets a shared portlet parameter.
-// *
-// * Internally, an action may be created and opened, as shared parameters
-// * cannot be set directly from all types of requests.
-// *
-// * The parameters and values need to be kept in the context until sent. Any
-// * memory leaks if the action fails are limited to the session.
-// *
-// * Shared parameters set or read by a portlet need to be declared in
-// * portlet.xml .
-// *
-// * @param window
-// * a window in which a temporary action URL can be opened if
-// * necessary
-// * @param name
-// * parameter identifier
-// * @param value
-// * parameter value
-// */
-// public void setSharedRenderParameter(Window window, String name,
-// String value) throws IllegalStateException {
-// if (response instanceof MimeResponse) {
-// String actionKey = "" + System.currentTimeMillis();
-// while (sharedParameterActionNameMap.containsKey(actionKey)) {
-// actionKey = actionKey + ".";
-// }
-// PortletURL actionUrl = generateActionURL(actionKey);
-// if (actionUrl != null) {
-// sharedParameterActionNameMap.put(actionKey, name);
-// sharedParameterActionValueMap.put(actionKey, value);
-// window.open(new ExternalResource(actionUrl.toString()));
-// } else {
-// // this should never happen as we already know the response is a
-// // MimeResponse
-// throw new IllegalStateException(
-// "Shared parameters can only be set from a portlet request");
-// }
-// } else if (response instanceof StateAwareResponse) {
-// ((StateAwareResponse) response).setRenderParameter(name, value);
-// } else {
-// throw new IllegalStateException(
-// "Shared parameters can only be set from a portlet request");
-// }
-// }
-//
-// /**
-// * Sets the portlet mode. This may trigger a new render request.
-// *
-// * Portlet modes used by a portlet need to be declared in portlet.xml .
-// *
-// * @param window
-// * a window in which the render URL can be opened if necessary
-// * @param portletMode
-// * the portlet mode to switch to
-// * @throws PortletModeException
-// * if the portlet mode is not allowed for some reason
-// * (configuration, permissions etc.)
-// */
-// public void setPortletMode(Window window, PortletMode portletMode)
-// throws IllegalStateException, PortletModeException {
-// if (response instanceof MimeResponse) {
-// PortletURL url = ((MimeResponse) response).createRenderURL();
-// url.setPortletMode(portletMode);
-// window.open(new ExternalResource(url.toString()));
-// } else if (response instanceof StateAwareResponse) {
-// ((StateAwareResponse) response).setPortletMode(portletMode);
-// } else {
-// throw new IllegalStateException(
-// "Portlet mode can only be changed from a portlet request");
-// }
-// }
-// }
+package com.vaadin.terminal.gwt.server;
+
+import java.io.File;
+import java.io.Serializable;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.portlet.ActionRequest;
+import javax.portlet.ActionResponse;
+import javax.portlet.EventRequest;
+import javax.portlet.EventResponse;
+import javax.portlet.MimeResponse;
+import javax.portlet.PortletConfig;
+import javax.portlet.PortletMode;
+import javax.portlet.PortletModeException;
+import javax.portlet.PortletResponse;
+import javax.portlet.PortletSession;
+import javax.portlet.PortletURL;
+import javax.portlet.RenderRequest;
+import javax.portlet.RenderResponse;
+import javax.portlet.ResourceRequest;
+import javax.portlet.ResourceResponse;
+import javax.portlet.ResourceURL;
+import javax.portlet.StateAwareResponse;
+import javax.servlet.http.HttpSessionBindingListener;
+import javax.xml.namespace.QName;
+
+import com.vaadin.Application;
+import com.vaadin.terminal.ApplicationResource;
+import com.vaadin.ui.Root;
+
+/**
+ * TODO Write documentation, fix JavaDoc tags.
+ *
+ * This is automatically registered as a {@link HttpSessionBindingListener} when
+ * {@link PortletSession#setAttribute()} is called with the context as value.
+ *
+ * @author peholmst
+ */
+@SuppressWarnings("serial")
+public class PortletApplicationContext2 extends AbstractWebApplicationContext {
+
+ private static final Logger logger = Logger
+ .getLogger(PortletApplicationContext2.class.getName());
+
+ protected Map<Application, Set<PortletListener>> portletListeners = new HashMap<Application, Set<PortletListener>>();
+
+ protected transient PortletSession session;
+ protected transient PortletConfig portletConfig;
+
+ protected HashMap<String, Application> portletWindowIdToApplicationMap = new HashMap<String, Application>();
+
+ private transient PortletResponse response;
+
+ private final Map<String, QName> eventActionDestinationMap = new HashMap<String, QName>();
+ private final Map<String, Serializable> eventActionValueMap = new HashMap<String, Serializable>();
+
+ private final Map<String, String> sharedParameterActionNameMap = new HashMap<String, String>();
+ private final Map<String, String> sharedParameterActionValueMap = new HashMap<String, String>();
+
+ public File getBaseDirectory() {
+ String resultPath = session.getPortletContext().getRealPath("/");
+ if (resultPath != null) {
+ return new File(resultPath);
+ } else {
+ try {
+ final URL url = session.getPortletContext().getResource("/");
+ return new File(url.getFile());
+ } catch (final Exception e) {
+ // FIXME: Handle exception
+ logger.log(
+ Level.INFO,
+ "Cannot access base directory, possible security issue "
+ + "with Application Server or Servlet Container",
+ e);
+ }
+ }
+ return null;
+ }
+
+ protected PortletCommunicationManager getApplicationManager(
+ Application application) {
+ PortletCommunicationManager mgr = (PortletCommunicationManager) applicationToAjaxAppMgrMap
+ .get(application);
+
+ if (mgr == null) {
+ // Creates a new manager
+ mgr = createPortletCommunicationManager(application);
+ applicationToAjaxAppMgrMap.put(application, mgr);
+ }
+ return mgr;
+ }
+
+ protected PortletCommunicationManager createPortletCommunicationManager(
+ Application application) {
+ return new PortletCommunicationManager(application);
+ }
+
+ public static PortletApplicationContext2 getApplicationContext(
+ PortletSession session) {
+ Object cxattr = session.getAttribute(PortletApplicationContext2.class
+ .getName());
+ PortletApplicationContext2 cx = null;
+ // can be false also e.g. if old context comes from another
+ // classloader when using
+ // <private-session-attributes>false</private-session-attributes>
+ // and redeploying the portlet - see #7461
+ if (cxattr instanceof PortletApplicationContext2) {
+ cx = (PortletApplicationContext2) cxattr;
+ }
+ if (cx == null) {
+ cx = new PortletApplicationContext2();
+ session.setAttribute(PortletApplicationContext2.class.getName(), cx);
+ }
+ if (cx.session == null) {
+ cx.session = session;
+ }
+ return cx;
+ }
+
+ @Override
+ protected void removeApplication(Application application) {
+ super.removeApplication(application);
+ // values() is backed by map, removes the key-value pair from the map
+ portletWindowIdToApplicationMap.values().remove(application);
+ }
+
+ protected void addApplication(Application application,
+ String portletWindowId) {
+ applications.add(application);
+ portletWindowIdToApplicationMap.put(portletWindowId, application);
+ }
+
+ public Application getApplicationForWindowId(String portletWindowId) {
+ return portletWindowIdToApplicationMap.get(portletWindowId);
+ }
+
+ public PortletSession getPortletSession() {
+ return session;
+ }
+
+ public PortletConfig getPortletConfig() {
+ return portletConfig;
+ }
+
+ public void setPortletConfig(PortletConfig config) {
+ portletConfig = config;
+ }
+
+ public void addPortletListener(Application app, PortletListener listener) {
+ Set<PortletListener> l = portletListeners.get(app);
+ if (l == null) {
+ l = new LinkedHashSet<PortletListener>();
+ portletListeners.put(app, l);
+ }
+ l.add(listener);
+ }
+
+ public void removePortletListener(Application app, PortletListener listener) {
+ Set<PortletListener> l = portletListeners.get(app);
+ if (l != null) {
+ l.remove(listener);
+ }
+ }
+
+ public void firePortletRenderRequest(Application app, Root root,
+ RenderRequest request, RenderResponse response) {
+ Set<PortletListener> listeners = portletListeners.get(app);
+ if (listeners != null) {
+ for (PortletListener l : listeners) {
+ l.handleRenderRequest(request, new RestrictedRenderResponse(
+ response), root);
+ }
+ }
+ }
+
+ public void firePortletActionRequest(Application app, Root root,
+ ActionRequest request, ActionResponse response) {
+ String key = request.getParameter(ActionRequest.ACTION_NAME);
+ if (eventActionDestinationMap.containsKey(key)) {
+ // this action request is only to send queued portlet events
+ response.setEvent(eventActionDestinationMap.get(key),
+ eventActionValueMap.get(key));
+ // cleanup
+ eventActionDestinationMap.remove(key);
+ eventActionValueMap.remove(key);
+ } else if (sharedParameterActionNameMap.containsKey(key)) {
+ // this action request is only to set shared render parameters
+ response.setRenderParameter(sharedParameterActionNameMap.get(key),
+ sharedParameterActionValueMap.get(key));
+ // cleanup
+ sharedParameterActionNameMap.remove(key);
+ sharedParameterActionValueMap.remove(key);
+ } else {
+ // normal action request, notify listeners
+ Set<PortletListener> listeners = portletListeners.get(app);
+ if (listeners != null) {
+ for (PortletListener l : listeners) {
+ l.handleActionRequest(request, response, root);
+ }
+ }
+ }
+ }
+
+ public void firePortletEventRequest(Application app, Root root,
+ EventRequest request, EventResponse response) {
+ Set<PortletListener> listeners = portletListeners.get(app);
+ if (listeners != null) {
+ for (PortletListener l : listeners) {
+ l.handleEventRequest(request, response, root);
+ }
+ }
+ }
+
+ public void firePortletResourceRequest(Application app, Root root,
+ ResourceRequest request, ResourceResponse response) {
+ Set<PortletListener> listeners = portletListeners.get(app);
+ if (listeners != null) {
+ for (PortletListener l : listeners) {
+ l.handleResourceRequest(request, response, root);
+ }
+ }
+ }
+
+ public interface PortletListener extends Serializable {
+
+ public void handleRenderRequest(RenderRequest request,
+ RenderResponse response, Root root);
+
+ public void handleActionRequest(ActionRequest request,
+ ActionResponse response, Root root);
+
+ public void handleEventRequest(EventRequest request,
+ EventResponse response, Root root);
+
+ public void handleResourceRequest(ResourceRequest request,
+ ResourceResponse response, Root root);
+ }
+
+ /**
+ * This is for use by {@link AbstractApplicationPortlet} only.
+ *
+ * TODO cleaner implementation, now "semi-static"!
+ *
+ * @param mimeResponse
+ */
+ void setResponse(PortletResponse response) {
+ this.response = response;
+ }
+
+ @Override
+ public String generateApplicationResourceURL(ApplicationResource resource,
+ String mapKey) {
+ if (response instanceof MimeResponse) {
+ ResourceURL resourceURL = ((MimeResponse) response)
+ .createResourceURL();
+ final String filename = resource.getFilename();
+ if (filename == null) {
+ resourceURL.setResourceID("APP/" + mapKey + "/");
+ } else {
+ resourceURL.setResourceID("APP/" + mapKey + "/"
+ + urlEncode(filename));
+ }
+ return resourceURL.toString();
+ } else {
+ // in a background thread or otherwise outside a request
+ // TODO exception ??
+ return null;
+ }
+ }
+
+ /**
+ * Creates a new action URL.
+ *
+ * @param action
+ * @return action URL or null if called outside a MimeRequest (outside a
+ * UIDL request or similar)
+ */
+ public PortletURL generateActionURL(String action) {
+ PortletURL url = null;
+ if (response instanceof MimeResponse) {
+ url = ((MimeResponse) response).createActionURL();
+ url.setParameter("javax.portlet.action", action);
+ } else {
+ return null;
+ }
+ return url;
+ }
+
+ /**
+ * Sends a portlet event to the indicated destination.
+ *
+ * Internally, an action may be created and opened, as an event cannot be
+ * sent directly from all types of requests.
+ *
+ * The event destinations and values need to be kept in the context until
+ * sent. Any memory leaks if the action fails are limited to the session.
+ *
+ * Event names for events sent and received by a portlet need to be declared
+ * in portlet.xml .
+ *
+ * @param root
+ * a window in which a temporary action URL can be opened if
+ * necessary
+ * @param name
+ * event name
+ * @param value
+ * event value object that is Serializable and, if appropriate,
+ * has a valid JAXB annotation
+ */
+ public void sendPortletEvent(Root root, QName name, Serializable value)
+ throws IllegalStateException {
+ if (response instanceof MimeResponse) {
+ String actionKey = "" + System.currentTimeMillis();
+ while (eventActionDestinationMap.containsKey(actionKey)) {
+ actionKey = actionKey + ".";
+ }
+ PortletURL actionUrl = generateActionURL(actionKey);
+ if (actionUrl != null) {
+ eventActionDestinationMap.put(actionKey, name);
+ eventActionValueMap.put(actionKey, value);
+ throw new RuntimeException(
+ "Root.open has not yet been implemented");
+ // root.open(new ExternalResource(actionUrl.toString()));
+ } else {
+ // this should never happen as we already know the response is a
+ // MimeResponse
+ throw new IllegalStateException(
+ "Portlet events can only be sent from a portlet request");
+ }
+ } else if (response instanceof StateAwareResponse) {
+ ((StateAwareResponse) response).setEvent(name, value);
+ } else {
+ throw new IllegalStateException(
+ "Portlet events can only be sent from a portlet request");
+ }
+ }
+
+ /**
+ * Sets a shared portlet parameter.
+ *
+ * Internally, an action may be created and opened, as shared parameters
+ * cannot be set directly from all types of requests.
+ *
+ * The parameters and values need to be kept in the context until sent. Any
+ * memory leaks if the action fails are limited to the session.
+ *
+ * Shared parameters set or read by a portlet need to be declared in
+ * portlet.xml .
+ *
+ * @param root
+ * a window in which a temporary action URL can be opened if
+ * necessary
+ * @param name
+ * parameter identifier
+ * @param value
+ * parameter value
+ */
+ public void setSharedRenderParameter(Root root, String name, String value)
+ throws IllegalStateException {
+ if (response instanceof MimeResponse) {
+ String actionKey = "" + System.currentTimeMillis();
+ while (sharedParameterActionNameMap.containsKey(actionKey)) {
+ actionKey = actionKey + ".";
+ }
+ PortletURL actionUrl = generateActionURL(actionKey);
+ if (actionUrl != null) {
+ sharedParameterActionNameMap.put(actionKey, name);
+ sharedParameterActionValueMap.put(actionKey, value);
+ throw new RuntimeException(
+ "Root.open has not yet been implemented");
+ // root.open(new ExternalResource(actionUrl.toString()));
+ } else {
+ // this should never happen as we already know the response is a
+ // MimeResponse
+ throw new IllegalStateException(
+ "Shared parameters can only be set from a portlet request");
+ }
+ } else if (response instanceof StateAwareResponse) {
+ ((StateAwareResponse) response).setRenderParameter(name, value);
+ } else {
+ throw new IllegalStateException(
+ "Shared parameters can only be set from a portlet request");
+ }
+ }
+
+ /**
+ * Sets the portlet mode. This may trigger a new render request.
+ *
+ * Portlet modes used by a portlet need to be declared in portlet.xml .
+ *
+ * @param root
+ * a window in which the render URL can be opened if necessary
+ * @param portletMode
+ * the portlet mode to switch to
+ * @throws PortletModeException
+ * if the portlet mode is not allowed for some reason
+ * (configuration, permissions etc.)
+ */
+ public void setPortletMode(Root root, PortletMode portletMode)
+ throws IllegalStateException, PortletModeException {
+ if (response instanceof MimeResponse) {
+ PortletURL url = ((MimeResponse) response).createRenderURL();
+ url.setPortletMode(portletMode);
+ throw new RuntimeException("Root.open has not yet been implemented");
+ // root.open(new ExternalResource(url.toString()));
+ } else if (response instanceof StateAwareResponse) {
+ ((StateAwareResponse) response).setPortletMode(portletMode);
+ } else {
+ throw new IllegalStateException(
+ "Portlet mode can only be changed from a portlet request");
+ }
+ }
+}
diff --git a/src/com/vaadin/terminal/gwt/server/PortletCommunicationManager.java b/src/com/vaadin/terminal/gwt/server/PortletCommunicationManager.java
index 6500e39b4b..466769b328 100644
--- a/src/com/vaadin/terminal/gwt/server/PortletCommunicationManager.java
+++ b/src/com/vaadin/terminal/gwt/server/PortletCommunicationManager.java
@@ -1,305 +1,304 @@
/*
@ITMillApache2LicenseForJavaFiles@
*/
-//package com.vaadin.terminal.gwt.server;
-//
-//import java.io.IOException;
-//import java.io.InputStream;
-//import java.io.OutputStream;
-//import java.lang.reflect.Method;
-//import java.util.HashMap;
-//import java.util.Map;
-//
-//import javax.portlet.ClientDataRequest;
-//import javax.portlet.MimeResponse;
-//import javax.portlet.PortletRequest;
-//import javax.portlet.PortletResponse;
-//import javax.portlet.PortletSession;
-//import javax.portlet.ResourceRequest;
-//import javax.portlet.ResourceResponse;
-//import javax.portlet.ResourceURL;
-//import javax.servlet.ServletException;
-//import javax.servlet.http.HttpServletRequestWrapper;
-//
-//import com.vaadin.Application;
-//import com.vaadin.terminal.DownloadStream;
-//import com.vaadin.terminal.Paintable;
-//import com.vaadin.terminal.StreamVariable;
-//import com.vaadin.terminal.VariableOwner;
-//import com.vaadin.ui.Component;
-//import com.vaadin.ui.Window;
-//
-///**
-// * TODO document me!
-// *
-// * @author peholmst
-// *
-// */
-//@SuppressWarnings("serial")
-//public class PortletCommunicationManager extends AbstractCommunicationManager {
-//
-// private transient ResourceResponse currentUidlResponse;
-//
-// private static class PortletRequestWrapper implements Request {
-//
-// private final PortletRequest request;
-//
-// public PortletRequestWrapper(PortletRequest request) {
-// this.request = request;
-// }
-//
-// public Object getAttribute(String name) {
-// return request.getAttribute(name);
-// }
-//
-// public int getContentLength() {
-// return ((ClientDataRequest) request).getContentLength();
-// }
-//
-// public InputStream getInputStream() throws IOException {
-// return ((ClientDataRequest) request).getPortletInputStream();
-// }
-//
-// public String getParameter(String name) {
-// String value = request.getParameter(name);
-// if (value == null) {
-// // for GateIn portlet container simple-portal
-// try {
-// Method getRealReq = request.getClass().getMethod(
-// "getRealRequest");
-// HttpServletRequestWrapper origRequest = (HttpServletRequestWrapper) getRealReq
-// .invoke(request);
-// value = origRequest.getParameter(name);
-// } catch (Exception e) {
-// // do nothing - not on GateIn simple-portal
-// }
-// }
-// return value;
-// }
-//
-// public String getRequestID() {
-// return "WindowID:" + request.getWindowID();
-// }
-//
-// public Session getSession() {
-// return new PortletSessionWrapper(request.getPortletSession());
-// }
-//
-// public Object getWrappedRequest() {
-// return request;
-// }
-//
-// public boolean isRunningInPortlet() {
-// return true;
-// }
-//
-// public void setAttribute(String name, Object o) {
-// request.setAttribute(name, o);
-// }
-//
-// }
-//
-// private static class PortletResponseWrapper implements Response {
-//
-// private final PortletResponse response;
-//
-// public PortletResponseWrapper(PortletResponse response) {
-// this.response = response;
-// }
-//
-// public OutputStream getOutputStream() throws IOException {
-// return ((MimeResponse) response).getPortletOutputStream();
-// }
-//
-// public Object getWrappedResponse() {
-// return response;
-// }
-//
-// public void setContentType(String type) {
-// ((MimeResponse) response).setContentType(type);
-// }
-// }
-//
-// private static class PortletSessionWrapper implements Session {
-//
-// private final PortletSession session;
-//
-// public PortletSessionWrapper(PortletSession session) {
-// this.session = session;
-// }
-//
-// public Object getAttribute(String name) {
-// return session.getAttribute(name);
-// }
-//
-// public int getMaxInactiveInterval() {
-// return session.getMaxInactiveInterval();
-// }
-//
-// public Object getWrappedSession() {
-// return session;
-// }
-//
-// public boolean isNew() {
-// return session.isNew();
-// }
-//
-// public void setAttribute(String name, Object o) {
-// session.setAttribute(name, o);
-// }
-//
-// }
-//
-// private static class AbstractApplicationPortletWrapper implements Callback {
-//
-// private final AbstractApplicationPortlet portlet;
-//
-// public AbstractApplicationPortletWrapper(
-// AbstractApplicationPortlet portlet) {
-// this.portlet = portlet;
-// }
-//
-// public void criticalNotification(Request request, Response response,
-// String cap, String msg, String details, String outOfSyncURL)
-// throws IOException {
-// portlet.criticalNotification(
-// (PortletRequest) request.getWrappedRequest(),
-// (MimeResponse) response.getWrappedResponse(), cap, msg,
-// details, outOfSyncURL);
-// }
-//
-// public String getRequestPathInfo(Request request) {
-// if (request.getWrappedRequest() instanceof ResourceRequest) {
-// return ((ResourceRequest) request.getWrappedRequest())
-// .getResourceID();
-// } else {
-// // We do not use paths in portlet mode
-// throw new UnsupportedOperationException(
-// "PathInfo only available when using ResourceRequests");
-// }
-// }
-//
-// public InputStream getThemeResourceAsStream(String themeName,
-// String resource) throws IOException {
-// return portlet.getPortletContext().getResourceAsStream(
-// "/" + AbstractApplicationPortlet.THEME_DIRECTORY_PATH
-// + themeName + "/" + resource);
-// }
-//
-// }
-//
-// public PortletCommunicationManager(Application application) {
-// super(application);
-// }
-//
-// public void handleFileUpload(ResourceRequest request,
-// ResourceResponse response) throws IOException {
-// String contentType = request.getContentType();
-// String name = request.getParameter("name");
-// String ownerId = request.getParameter("rec-owner");
-// VariableOwner variableOwner = getVariableOwner(ownerId);
-// StreamVariable streamVariable = ownerToNameToStreamVariable.get(
-// variableOwner).get(name);
-//
-// if (contentType.contains("boundary")) {
-// doHandleSimpleMultipartFileUpload(
-// new PortletRequestWrapper(request),
-// new PortletResponseWrapper(response), streamVariable, name,
-// variableOwner, contentType.split("boundary=")[1]);
-// } else {
-// doHandleXhrFilePost(new PortletRequestWrapper(request),
-// new PortletResponseWrapper(response), streamVariable, name,
-// variableOwner, request.getContentLength());
-// }
-//
-// }
-//
-// @Override
-// protected void unregisterPaintable(Component p) {
-// super.unregisterPaintable(p);
-// if (ownerToNameToStreamVariable != null) {
-// ownerToNameToStreamVariable.remove(p);
-// }
-// }
-//
-// public void handleUidlRequest(ResourceRequest request,
-// ResourceResponse response,
-// AbstractApplicationPortlet applicationPortlet, Window window)
-// throws InvalidUIDLSecurityKeyException, IOException {
-// currentUidlResponse = response;
-// doHandleUidlRequest(new PortletRequestWrapper(request),
-// new PortletResponseWrapper(response),
-// new AbstractApplicationPortletWrapper(applicationPortlet),
-// window);
-// currentUidlResponse = null;
-// }
-//
-// DownloadStream handleURI(Window window, ResourceRequest request,
-// ResourceResponse response,
-// AbstractApplicationPortlet applicationPortlet) {
-// return handleURI(window, new PortletRequestWrapper(request),
-// new PortletResponseWrapper(response),
-// new AbstractApplicationPortletWrapper(applicationPortlet));
-// }
-//
-// /**
-// * Gets the existing application or creates a new one. Get a window within
-// * an application based on the requested URI.
-// *
-// * @param request
-// * the portlet Request.
-// * @param applicationPortlet
-// * @param application
-// * the Application to query for window.
-// * @param assumedWindow
-// * if the window has been already resolved once, this parameter
-// * must contain the window.
-// * @return Window matching the given URI or null if not found.
-// * @throws ServletException
-// * if an exception has occurred that interferes with the
-// * servlet's normal operation.
-// */
-// Window getApplicationWindow(PortletRequest request,
-// AbstractApplicationPortlet applicationPortlet,
-// Application application, Window assumedWindow) {
-//
-// return doGetApplicationWindow(new PortletRequestWrapper(request),
-// new AbstractApplicationPortletWrapper(applicationPortlet),
-// application, assumedWindow);
-// }
-//
-// private Map<VariableOwner, Map<String, StreamVariable>> ownerToNameToStreamVariable;
-//
-// @Override
-// String getStreamVariableTargetUrl(VariableOwner owner, String name,
-// StreamVariable value) {
-// if (ownerToNameToStreamVariable == null) {
-// ownerToNameToStreamVariable = new HashMap<VariableOwner, Map<String, StreamVariable>>();
-// }
-// Map<String, StreamVariable> nameToReceiver = ownerToNameToStreamVariable
-// .get(owner);
-// if (nameToReceiver == null) {
-// nameToReceiver = new HashMap<String, StreamVariable>();
-// ownerToNameToStreamVariable.put(owner, nameToReceiver);
-// }
-// nameToReceiver.put(name, value);
-// ResourceURL resurl = currentUidlResponse.createResourceURL();
-// resurl.setResourceID("UPLOAD");
-// resurl.setParameter("name", name);
-// resurl.setParameter("rec-owner", getPaintableId((Paintable) owner));
-// resurl.setProperty("name", name);
-// resurl.setProperty("rec-owner", getPaintableId((Paintable) owner));
-// return resurl.toString();
-// }
-//
-// @Override
-// protected void cleanStreamVariable(VariableOwner owner, String name) {
-// Map<String, StreamVariable> map = ownerToNameToStreamVariable
-// .get(owner);
-// map.remove(name);
-// if (map.isEmpty()) {
-// ownerToNameToStreamVariable.remove(owner);
-// }
-// }
-//
-// }
+package com.vaadin.terminal.gwt.server;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.portlet.ClientDataRequest;
+import javax.portlet.MimeResponse;
+import javax.portlet.PortletRequest;
+import javax.portlet.PortletResponse;
+import javax.portlet.PortletSession;
+import javax.portlet.ResourceRequest;
+import javax.portlet.ResourceResponse;
+import javax.portlet.ResourceURL;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequestWrapper;
+
+import com.vaadin.Application;
+import com.vaadin.terminal.DownloadStream;
+import com.vaadin.terminal.Paintable;
+import com.vaadin.terminal.StreamVariable;
+import com.vaadin.terminal.VariableOwner;
+import com.vaadin.ui.Component;
+import com.vaadin.ui.Root;
+
+/**
+ * TODO document me!
+ *
+ * @author peholmst
+ *
+ */
+@SuppressWarnings("serial")
+public class PortletCommunicationManager extends AbstractCommunicationManager {
+
+ private transient ResourceResponse currentUidlResponse;
+
+ private static class PortletRequestWrapper implements Request {
+
+ private final PortletRequest request;
+
+ public PortletRequestWrapper(PortletRequest request) {
+ this.request = request;
+ }
+
+ public Object getAttribute(String name) {
+ return request.getAttribute(name);
+ }
+
+ public int getContentLength() {
+ return ((ClientDataRequest) request).getContentLength();
+ }
+
+ public InputStream getInputStream() throws IOException {
+ return ((ClientDataRequest) request).getPortletInputStream();
+ }
+
+ public String getParameter(String name) {
+ String value = request.getParameter(name);
+ if (value == null) {
+ // for GateIn portlet container simple-portal
+ try {
+ Method getRealReq = request.getClass().getMethod(
+ "getRealRequest");
+ HttpServletRequestWrapper origRequest = (HttpServletRequestWrapper) getRealReq
+ .invoke(request);
+ value = origRequest.getParameter(name);
+ } catch (Exception e) {
+ // do nothing - not on GateIn simple-portal
+ }
+ }
+ return value;
+ }
+
+ public String getRequestID() {
+ return "WindowID:" + request.getWindowID();
+ }
+
+ public Session getSession() {
+ return new PortletSessionWrapper(request.getPortletSession());
+ }
+
+ public Object getWrappedRequest() {
+ return request;
+ }
+
+ public boolean isRunningInPortlet() {
+ return true;
+ }
+
+ public void setAttribute(String name, Object o) {
+ request.setAttribute(name, o);
+ }
+
+ }
+
+ private static class PortletResponseWrapper implements Response {
+
+ private final PortletResponse response;
+
+ public PortletResponseWrapper(PortletResponse response) {
+ this.response = response;
+ }
+
+ public OutputStream getOutputStream() throws IOException {
+ return ((MimeResponse) response).getPortletOutputStream();
+ }
+
+ public Object getWrappedResponse() {
+ return response;
+ }
+
+ public void setContentType(String type) {
+ ((MimeResponse) response).setContentType(type);
+ }
+ }
+
+ private static class PortletSessionWrapper implements Session {
+
+ private final PortletSession session;
+
+ public PortletSessionWrapper(PortletSession session) {
+ this.session = session;
+ }
+
+ public Object getAttribute(String name) {
+ return session.getAttribute(name);
+ }
+
+ public int getMaxInactiveInterval() {
+ return session.getMaxInactiveInterval();
+ }
+
+ public Object getWrappedSession() {
+ return session;
+ }
+
+ public boolean isNew() {
+ return session.isNew();
+ }
+
+ public void setAttribute(String name, Object o) {
+ session.setAttribute(name, o);
+ }
+
+ }
+
+ private static class AbstractApplicationPortletWrapper implements Callback {
+
+ private final AbstractApplicationPortlet portlet;
+
+ public AbstractApplicationPortletWrapper(
+ AbstractApplicationPortlet portlet) {
+ this.portlet = portlet;
+ }
+
+ public void criticalNotification(Request request, Response response,
+ String cap, String msg, String details, String outOfSyncURL)
+ throws IOException {
+ portlet.criticalNotification(
+ (PortletRequest) request.getWrappedRequest(),
+ (MimeResponse) response.getWrappedResponse(), cap, msg,
+ details, outOfSyncURL);
+ }
+
+ public String getRequestPathInfo(Request request) {
+ if (request.getWrappedRequest() instanceof ResourceRequest) {
+ return ((ResourceRequest) request.getWrappedRequest())
+ .getResourceID();
+ } else {
+ // We do not use paths in portlet mode
+ throw new UnsupportedOperationException(
+ "PathInfo only available when using ResourceRequests");
+ }
+ }
+
+ public InputStream getThemeResourceAsStream(String themeName,
+ String resource) throws IOException {
+ return portlet.getPortletContext().getResourceAsStream(
+ "/" + AbstractApplicationPortlet.THEME_DIRECTORY_PATH
+ + themeName + "/" + resource);
+ }
+
+ }
+
+ public PortletCommunicationManager(Application application) {
+ super(application);
+ }
+
+ public void handleFileUpload(ResourceRequest request,
+ ResourceResponse response) throws IOException {
+ String contentType = request.getContentType();
+ String name = request.getParameter("name");
+ String ownerId = request.getParameter("rec-owner");
+ VariableOwner variableOwner = getVariableOwner(ownerId);
+ StreamVariable streamVariable = ownerToNameToStreamVariable.get(
+ variableOwner).get(name);
+
+ if (contentType.contains("boundary")) {
+ doHandleSimpleMultipartFileUpload(
+ new PortletRequestWrapper(request),
+ new PortletResponseWrapper(response), streamVariable, name,
+ variableOwner, contentType.split("boundary=")[1]);
+ } else {
+ doHandleXhrFilePost(new PortletRequestWrapper(request),
+ new PortletResponseWrapper(response), streamVariable, name,
+ variableOwner, request.getContentLength());
+ }
+
+ }
+
+ @Override
+ protected void unregisterPaintable(Component p) {
+ super.unregisterPaintable(p);
+ if (ownerToNameToStreamVariable != null) {
+ ownerToNameToStreamVariable.remove(p);
+ }
+ }
+
+ public void handleUidlRequest(ResourceRequest request,
+ ResourceResponse response,
+ AbstractApplicationPortlet applicationPortlet, Root root)
+ throws InvalidUIDLSecurityKeyException, IOException {
+ currentUidlResponse = response;
+ doHandleUidlRequest(new PortletRequestWrapper(request),
+ new PortletResponseWrapper(response),
+ new AbstractApplicationPortletWrapper(applicationPortlet), root);
+ currentUidlResponse = null;
+ }
+
+ DownloadStream handleURI(Root root, ResourceRequest request,
+ ResourceResponse response,
+ AbstractApplicationPortlet applicationPortlet) {
+ return handleURI(root, new PortletRequestWrapper(request),
+ new PortletResponseWrapper(response),
+ new AbstractApplicationPortletWrapper(applicationPortlet));
+ }
+
+ /**
+ * Gets the existing application or creates a new one. Get a window within
+ * an application based on the requested URI.
+ *
+ * @param request
+ * the portlet Request.
+ * @param applicationPortlet
+ * @param application
+ * the Application to query for window.
+ * @param assumedRoot
+ * if the window has been already resolved once, this parameter
+ * must contain the window.
+ * @return Window matching the given URI or null if not found.
+ * @throws ServletException
+ * if an exception has occurred that interferes with the
+ * servlet's normal operation.
+ */
+ Root getApplicationRoot(PortletRequest request,
+ AbstractApplicationPortlet applicationPortlet,
+ Application application, Root assumedRoot) {
+
+ return doGetApplicationWindow(new PortletRequestWrapper(request),
+ new AbstractApplicationPortletWrapper(applicationPortlet),
+ application, assumedRoot);
+ }
+
+ private Map<VariableOwner, Map<String, StreamVariable>> ownerToNameToStreamVariable;
+
+ @Override
+ String getStreamVariableTargetUrl(VariableOwner owner, String name,
+ StreamVariable value) {
+ if (ownerToNameToStreamVariable == null) {
+ ownerToNameToStreamVariable = new HashMap<VariableOwner, Map<String, StreamVariable>>();
+ }
+ Map<String, StreamVariable> nameToReceiver = ownerToNameToStreamVariable
+ .get(owner);
+ if (nameToReceiver == null) {
+ nameToReceiver = new HashMap<String, StreamVariable>();
+ ownerToNameToStreamVariable.put(owner, nameToReceiver);
+ }
+ nameToReceiver.put(name, value);
+ ResourceURL resurl = currentUidlResponse.createResourceURL();
+ resurl.setResourceID("UPLOAD");
+ resurl.setParameter("name", name);
+ resurl.setParameter("rec-owner", getPaintableId((Paintable) owner));
+ resurl.setProperty("name", name);
+ resurl.setProperty("rec-owner", getPaintableId((Paintable) owner));
+ return resurl.toString();
+ }
+
+ @Override
+ protected void cleanStreamVariable(VariableOwner owner, String name) {
+ Map<String, StreamVariable> map = ownerToNameToStreamVariable
+ .get(owner);
+ map.remove(name);
+ if (map.isEmpty()) {
+ ownerToNameToStreamVariable.remove(owner);
+ }
+ }
+
+}