summaryrefslogtreecommitdiffstats
path: root/src/com/vaadin/terminal/gwt/server
diff options
context:
space:
mode:
authorJohannes Dahlström <johannesd@vaadin.com>2012-08-17 13:32:54 +0300
committerJohannes Dahlström <johannesd@vaadin.com>2012-08-17 13:32:54 +0300
commit47a0326c2fb2d6d8621e7a6fbfa2f011a48e15a4 (patch)
tree416685c3912f716eb09497cc7cce071786fe2d12 /src/com/vaadin/terminal/gwt/server
parent8e3aa0a9823556896f1af00599c3e79ca2ce2e01 (diff)
parent9bdbd7efbb7fa599910dc85182968334e4dced78 (diff)
downloadvaadin-framework-47a0326c2fb2d6d8621e7a6fbfa2f011a48e15a4.tar.gz
vaadin-framework-47a0326c2fb2d6d8621e7a6fbfa2f011a48e15a4.zip
Merge branch 'master' into root-cleanup
Conflicts: server/src/com/vaadin/terminal/DeploymentConfiguration.java server/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java server/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java server/src/com/vaadin/terminal/gwt/server/AbstractDeploymentConfiguration.java
Diffstat (limited to 'src/com/vaadin/terminal/gwt/server')
-rw-r--r--src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java1046
-rw-r--r--src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java1572
-rw-r--r--src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java2791
-rw-r--r--src/com/vaadin/terminal/gwt/server/AbstractDeploymentConfiguration.java210
-rw-r--r--src/com/vaadin/terminal/gwt/server/AbstractStreamingEvent.java46
-rw-r--r--src/com/vaadin/terminal/gwt/server/AbstractWebApplicationContext.java268
-rw-r--r--src/com/vaadin/terminal/gwt/server/ApplicationPortlet2.java38
-rw-r--r--src/com/vaadin/terminal/gwt/server/ApplicationResourceHandler.java55
-rw-r--r--src/com/vaadin/terminal/gwt/server/ApplicationServlet.java78
-rw-r--r--src/com/vaadin/terminal/gwt/server/BootstrapDom.java9
-rw-r--r--src/com/vaadin/terminal/gwt/server/BootstrapHandler.java643
-rw-r--r--src/com/vaadin/terminal/gwt/server/BootstrapListener.java11
-rw-r--r--src/com/vaadin/terminal/gwt/server/BootstrapResponse.java72
-rw-r--r--src/com/vaadin/terminal/gwt/server/ChangeVariablesErrorEvent.java39
-rw-r--r--src/com/vaadin/terminal/gwt/server/ClientConnector.java149
-rw-r--r--src/com/vaadin/terminal/gwt/server/ClientMethodInvocation.java71
-rw-r--r--src/com/vaadin/terminal/gwt/server/CommunicationManager.java122
-rw-r--r--src/com/vaadin/terminal/gwt/server/ComponentSizeValidator.java664
-rw-r--r--src/com/vaadin/terminal/gwt/server/Constants.java80
-rw-r--r--src/com/vaadin/terminal/gwt/server/DragAndDropService.java313
-rw-r--r--src/com/vaadin/terminal/gwt/server/GAEApplicationServlet.java417
-rw-r--r--src/com/vaadin/terminal/gwt/server/HttpServletRequestListener.java54
-rw-r--r--src/com/vaadin/terminal/gwt/server/JsonCodec.java792
-rw-r--r--src/com/vaadin/terminal/gwt/server/JsonPaintTarget.java1022
-rw-r--r--src/com/vaadin/terminal/gwt/server/LegacyChangeVariablesInvocation.java38
-rw-r--r--src/com/vaadin/terminal/gwt/server/NoInputStreamException.java9
-rw-r--r--src/com/vaadin/terminal/gwt/server/NoOutputStreamException.java9
-rw-r--r--src/com/vaadin/terminal/gwt/server/PortletApplicationContext2.java398
-rw-r--r--src/com/vaadin/terminal/gwt/server/PortletCommunicationManager.java170
-rw-r--r--src/com/vaadin/terminal/gwt/server/PortletRequestListener.java56
-rw-r--r--src/com/vaadin/terminal/gwt/server/RequestTimer.java43
-rw-r--r--src/com/vaadin/terminal/gwt/server/ResourceReference.java67
-rw-r--r--src/com/vaadin/terminal/gwt/server/RestrictedRenderResponse.java172
-rw-r--r--src/com/vaadin/terminal/gwt/server/RpcManager.java48
-rw-r--r--src/com/vaadin/terminal/gwt/server/RpcTarget.java28
-rw-r--r--src/com/vaadin/terminal/gwt/server/ServerRpcManager.java142
-rw-r--r--src/com/vaadin/terminal/gwt/server/ServerRpcMethodInvocation.java113
-rw-r--r--src/com/vaadin/terminal/gwt/server/ServletPortletHelper.java120
-rw-r--r--src/com/vaadin/terminal/gwt/server/SessionExpiredException.java9
-rw-r--r--src/com/vaadin/terminal/gwt/server/StreamingEndEventImpl.java16
-rw-r--r--src/com/vaadin/terminal/gwt/server/StreamingErrorEventImpl.java25
-rw-r--r--src/com/vaadin/terminal/gwt/server/StreamingProgressEventImpl.java17
-rw-r--r--src/com/vaadin/terminal/gwt/server/StreamingStartEventImpl.java28
-rw-r--r--src/com/vaadin/terminal/gwt/server/SystemMessageException.java57
-rw-r--r--src/com/vaadin/terminal/gwt/server/UnsupportedBrowserHandler.java89
-rw-r--r--src/com/vaadin/terminal/gwt/server/UploadException.java15
-rw-r--r--src/com/vaadin/terminal/gwt/server/VaadinContext.java61
-rw-r--r--src/com/vaadin/terminal/gwt/server/VaadinContextEvent.java19
-rw-r--r--src/com/vaadin/terminal/gwt/server/VaadinContextListener.java13
-rw-r--r--src/com/vaadin/terminal/gwt/server/WebApplicationContext.java180
-rw-r--r--src/com/vaadin/terminal/gwt/server/WebBrowser.java462
-rw-r--r--src/com/vaadin/terminal/gwt/server/WrappedHttpServletRequest.java118
-rw-r--r--src/com/vaadin/terminal/gwt/server/WrappedHttpServletResponse.java75
-rw-r--r--src/com/vaadin/terminal/gwt/server/WrappedPortletRequest.java217
-rw-r--r--src/com/vaadin/terminal/gwt/server/WrappedPortletResponse.java111
55 files changed, 0 insertions, 13487 deletions
diff --git a/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java b/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java
deleted file mode 100644
index bfd35fd034..0000000000
--- a/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java
+++ /dev/null
@@ -1,1046 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-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.Enumeration;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Properties;
-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.PortletConfig;
-import javax.portlet.PortletContext;
-import javax.portlet.PortletException;
-import javax.portlet.PortletRequest;
-import javax.portlet.PortletResponse;
-import javax.portlet.PortletSession;
-import javax.portlet.RenderRequest;
-import javax.portlet.RenderResponse;
-import javax.portlet.ResourceRequest;
-import javax.portlet.ResourceResponse;
-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.ApplicationStartEvent;
-import com.vaadin.Application.SystemMessages;
-import com.vaadin.RootRequiresMoreInformationException;
-import com.vaadin.terminal.DeploymentConfiguration;
-import com.vaadin.terminal.Terminal;
-import com.vaadin.terminal.WrappedRequest;
-import com.vaadin.terminal.WrappedResponse;
-import com.vaadin.terminal.gwt.server.AbstractCommunicationManager.Callback;
-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 {
-
- public static final String RESOURCE_URL_ID = "APP";
-
- public static class WrappedHttpAndPortletRequest extends
- WrappedPortletRequest {
-
- public WrappedHttpAndPortletRequest(PortletRequest request,
- HttpServletRequest originalRequest,
- DeploymentConfiguration deploymentConfiguration) {
- super(request, deploymentConfiguration);
- this.originalRequest = originalRequest;
- }
-
- private final HttpServletRequest originalRequest;
-
- @Override
- public String getParameter(String name) {
- String parameter = super.getParameter(name);
- if (parameter == null) {
- parameter = originalRequest.getParameter(name);
- }
- return parameter;
- }
-
- @Override
- public String getRemoteAddr() {
- return originalRequest.getRemoteAddr();
- }
-
- @Override
- public String getHeader(String name) {
- String header = super.getHeader(name);
- if (header == null) {
- header = originalRequest.getHeader(name);
- }
- return header;
- }
-
- @Override
- public Map<String, String[]> getParameterMap() {
- Map<String, String[]> parameterMap = super.getParameterMap();
- if (parameterMap == null) {
- parameterMap = originalRequest.getParameterMap();
- }
- return parameterMap;
- }
- }
-
- public static class WrappedGateinRequest extends
- WrappedHttpAndPortletRequest {
- public WrappedGateinRequest(PortletRequest request,
- DeploymentConfiguration deploymentConfiguration) {
- super(request, getOriginalRequest(request), deploymentConfiguration);
- }
-
- private static final HttpServletRequest getOriginalRequest(
- PortletRequest request) {
- try {
- Method getRealReq = request.getClass().getMethod(
- "getRealRequest");
- HttpServletRequestWrapper origRequest = (HttpServletRequestWrapper) getRealReq
- .invoke(request);
- return origRequest;
- } catch (Exception e) {
- throw new IllegalStateException("GateIn request not detected",
- e);
- }
- }
- }
-
- public static class WrappedLiferayRequest extends
- WrappedHttpAndPortletRequest {
-
- public WrappedLiferayRequest(PortletRequest request,
- DeploymentConfiguration deploymentConfiguration) {
- super(request, getOriginalRequest(request), deploymentConfiguration);
- }
-
- @Override
- public String getPortalProperty(String name) {
- return PropsUtil.get(name);
- }
-
- private static HttpServletRequest getOriginalRequest(
- PortletRequest request) {
- 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);
- return httpRequest;
- } catch (Exception e) {
- throw new IllegalStateException("Liferay request not detected",
- e);
- }
- }
-
- }
-
- public static class AbstractApplicationPortletWrapper implements Callback {
-
- private final AbstractApplicationPortlet portlet;
-
- public AbstractApplicationPortletWrapper(
- AbstractApplicationPortlet portlet) {
- this.portlet = portlet;
- }
-
- @Override
- public void criticalNotification(WrappedRequest request,
- WrappedResponse response, String cap, String msg,
- String details, String outOfSyncURL) throws IOException {
- portlet.criticalNotification(WrappedPortletRequest.cast(request),
- (WrappedPortletResponse) response, cap, msg, details,
- outOfSyncURL);
- }
- }
-
- /**
- * 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";
-
- /**
- * This portal parameter is used to define the name of the Vaadin theme that
- * is used for all Vaadin applications in the portal.
- */
- public static final String PORTAL_PARAMETER_VAADIN_THEME = "vaadin.theme";
-
- public static final String WRITE_AJAX_PAGE_SCRIPT_WIDGETSET_SHOULD_WRITE = "writeAjaxPageScriptWidgetsetShouldWrite";
-
- // 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?
-
- private boolean productionMode = false;
-
- private DeploymentConfiguration deploymentConfiguration = new AbstractDeploymentConfiguration(
- getClass()) {
- @Override
- public String getConfiguredWidgetset(WrappedRequest request) {
-
- String widgetset = getApplicationOrSystemProperty(
- PARAMETER_WIDGETSET, null);
-
- if (widgetset == null) {
- // If no widgetset defined for the application, check the
- // portal
- // property
- widgetset = WrappedPortletRequest.cast(request)
- .getPortalProperty(PORTAL_PARAMETER_VAADIN_WIDGETSET);
- }
-
- if (widgetset == null) {
- // If no widgetset defined for the portal, use the default
- widgetset = DEFAULT_WIDGETSET;
- }
-
- return widgetset;
- }
-
- @Override
- public String getConfiguredTheme(WrappedRequest request) {
-
- // is the default theme defined by the portal?
- String themeName = WrappedPortletRequest.cast(request)
- .getPortalProperty(Constants.PORTAL_PARAMETER_VAADIN_THEME);
-
- if (themeName == null) {
- // no, using the default theme defined by Vaadin
- themeName = DEFAULT_THEME_NAME;
- }
-
- return themeName;
- }
-
- @Override
- public boolean isStandalone(WrappedRequest request) {
- return false;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.vaadin.terminal.DeploymentConfiguration#getStaticFileLocation
- * (com.vaadin.terminal.WrappedRequest)
- *
- * 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.
- *
- * @return The location of static resources (inside which there should
- * be a VAADIN directory). Does not end with a slash (/).
- */
-
- @Override
- public String getStaticFileLocation(WrappedRequest request) {
- String staticFileLocation = WrappedPortletRequest.cast(request)
- .getPortalProperty(
- Constants.PORTAL_PARAMETER_VAADIN_RESOURCE_PATH);
- 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";
- }
- }
-
- @Override
- public String getMimeType(String resourceName) {
- return getPortletContext().getMimeType(resourceName);
- }
- };
-
- private final VaadinContext vaadinContext = new VaadinContext(
- getDeploymentConfiguration());
-
- @Override
- public void init(PortletConfig config) throws PortletException {
- super.init(config);
- Properties applicationProperties = getDeploymentConfiguration()
- .getInitParameters();
-
- // Read default parameters from the context
- 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));
- }
-
- // Override with application settings from portlet.xml
- for (final Enumeration<String> e = config.getInitParameterNames(); e
- .hasMoreElements();) {
- final String name = e.nextElement();
- applicationProperties.setProperty(name,
- config.getInitParameter(name));
- }
-
- vaadinContext.init();
- }
-
- @Override
- public void destroy() {
- super.destroy();
-
- vaadinContext.destroy();
- }
-
- protected enum RequestType {
- FILE_UPLOAD, UIDL, RENDER, STATIC_FILE, APPLICATION_RESOURCE, DUMMY, EVENT, ACTION, UNKNOWN, BROWSER_DETAILS, CONNECTOR_RESOURCE;
- }
-
- protected RequestType getRequestType(WrappedPortletRequest wrappedRequest) {
- PortletRequest request = wrappedRequest.getPortletRequest();
- if (request instanceof RenderRequest) {
- return RequestType.RENDER;
- } else if (request instanceof ResourceRequest) {
- ResourceRequest resourceRequest = (ResourceRequest) request;
- if (ServletPortletHelper.isUIDLRequest(wrappedRequest)) {
- return RequestType.UIDL;
- } else if (isBrowserDetailsRequest(resourceRequest)) {
- return RequestType.BROWSER_DETAILS;
- } else if (ServletPortletHelper.isFileUploadRequest(wrappedRequest)) {
- return RequestType.FILE_UPLOAD;
- } else if (ServletPortletHelper
- .isConnectorResourceRequest(wrappedRequest)) {
- return RequestType.CONNECTOR_RESOURCE;
- } else if (ServletPortletHelper
- .isApplicationResourceRequest(wrappedRequest)) {
- return RequestType.APPLICATION_RESOURCE;
- } else if (isDummyRequest(resourceRequest)) {
- 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 isBrowserDetailsRequest(ResourceRequest request) {
- return request.getResourceID() != null
- && request.getResourceID().equals("browserDetails");
- }
-
- private boolean isDummyRequest(ResourceRequest request) {
- return request.getResourceID() != null
- && request.getResourceID().equals("DUMMY");
- }
-
- /**
- * 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 {
- RequestTimer requestTimer = new RequestTimer();
- requestTimer.start();
-
- AbstractApplicationPortletWrapper portletWrapper = new AbstractApplicationPortletWrapper(
- this);
-
- WrappedPortletRequest wrappedRequest = createWrappedRequest(request);
-
- WrappedPortletResponse wrappedResponse = new WrappedPortletResponse(
- response, getDeploymentConfiguration());
-
- RequestType requestType = getRequestType(wrappedRequest);
-
- 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(wrappedRequest,
- requestType);
- if (application == null) {
- return;
- }
- Application.setCurrent(application);
-
- /*
- * 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);
-
- if (requestType == RequestType.CONNECTOR_RESOURCE) {
- applicationManager.serveConnectorResource(wrappedRequest,
- wrappedResponse);
- return;
- }
-
- /* Update browser information from request */
- applicationContext.getBrowser().updateRequestDetails(
- wrappedRequest);
-
- /*
- * 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 RENDER:
- case ACTION:
- // Both action requests and render requests are ok
- // without a Root as they render the initial HTML
- // and then do a second request
- try {
- root = application
- .getRootForRequest(wrappedRequest);
- } catch (RootRequiresMoreInformationException e) {
- // Ignore problem and continue without root
- }
- break;
- case BROWSER_DETAILS:
- // Should not try to find a root here as the
- // combined request details might change the root
- break;
- case FILE_UPLOAD:
- // no window
- break;
- case APPLICATION_RESOURCE:
- // use main window - should not need any window
- // root = application.getRoot();
- break;
- default:
- root = application
- .getRootForRequest(wrappedRequest);
- }
- // 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) {
- // Root is resolved in handleFileUpload by
- // PortletCommunicationManager
- applicationManager.handleFileUpload(application,
- wrappedRequest, wrappedResponse);
- return;
- } else if (requestType == RequestType.BROWSER_DETAILS) {
- applicationManager.handleBrowserDetailsRequest(
- wrappedRequest, wrappedResponse, application);
- return;
- } else if (requestType == RequestType.UIDL) {
- // Handles AJAX UIDL requests
- applicationManager.handleUidlRequest(wrappedRequest,
- wrappedResponse, portletWrapper, root);
- return;
- } else {
- /*
- * Removes the application if it has stopped
- */
- if (!application.isRunning()) {
- endApplication(request, response, application);
- return;
- }
-
- handleOtherRequest(wrappedRequest, wrappedResponse,
- requestType, application, applicationContext,
- applicationManager);
- }
- } catch (final SessionExpiredException e) {
- // TODO Figure out a better way to deal with
- // SessionExpiredExceptions
- getLogger().finest("A user session has expired");
- } catch (final GeneralSecurityException e) {
- // TODO Figure out a better way to deal with
- // GeneralSecurityExceptions
- getLogger()
- .fine("General security exception, the security key was probably incorrect.");
- } catch (final Throwable e) {
- handleServiceException(wrappedRequest, wrappedResponse,
- application, e);
- } finally {
- // Notifies transaction end
- try {
- if (transactionStarted) {
- ((PortletApplicationContext2) application.getContext())
- .endTransaction(application, request);
- }
- } finally {
- try {
- if (requestStarted) {
- ((PortletRequestListener) application)
- .onRequestEnd(request, response);
-
- }
- } finally {
- Root.setCurrent(null);
- Application.setCurrent(null);
-
- PortletSession session = request
- .getPortletSession(false);
- if (session != null) {
- requestTimer.stop(getApplicationContext(session));
- }
- }
- }
- }
- }
- }
-
- /**
- * Wraps the request in a (possibly portal specific) wrapped portlet
- * request.
- *
- * @param request
- * The original PortletRequest
- * @return A wrapped version of the PorletRequest
- */
- protected WrappedPortletRequest createWrappedRequest(PortletRequest request) {
- String portalInfo = request.getPortalContext().getPortalInfo()
- .toLowerCase();
- if (portalInfo.contains("liferay")) {
- return new WrappedLiferayRequest(request,
- getDeploymentConfiguration());
- } else if (portalInfo.contains("gatein")) {
- return new WrappedGateinRequest(request,
- getDeploymentConfiguration());
- } else {
- return new WrappedPortletRequest(request,
- getDeploymentConfiguration());
- }
-
- }
-
- protected DeploymentConfiguration getDeploymentConfiguration() {
- return deploymentConfiguration;
- }
-
- private void handleUnknownRequest(PortletRequest request,
- PortletResponse response) {
- getLogger().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(WrappedPortletRequest request,
- WrappedResponse response, RequestType requestType,
- Application application,
- PortletApplicationContext2 applicationContext,
- PortletCommunicationManager applicationManager)
- throws PortletException, IOException, MalformedURLException {
- if (requestType == RequestType.APPLICATION_RESOURCE
- || requestType == RequestType.RENDER) {
- if (!applicationManager.handleApplicationRequest(request, response)) {
- response.sendError(HttpServletResponse.SC_NOT_FOUND,
- "Not found");
- }
- } 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!");
- }
- }
-
- @Override
- public void processEvent(EventRequest request, EventResponse response)
- throws PortletException, IOException {
- handleRequest(request, response);
- }
-
- 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 {
- getLogger().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(new ApplicationStartEvent(null,
- getDeploymentConfiguration(), 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(
- WrappedPortletRequest wrappedRequest, RequestType requestType)
- throws PortletException, SessionExpiredException,
- MalformedURLException {
- PortletRequest request = wrappedRequest.getPortletRequest();
-
- 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 = (wrappedRequest
- .getParameter(URL_PARAMETER_RESTART_APPLICATION) != null);
- final boolean closeApplication = (wrappedRequest
- .getParameter(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;
- }
-
- protected abstract Class<? extends Application> getApplicationClass()
- throws ClassNotFoundException;
-
- protected Application getNewApplication(PortletRequest request)
- throws PortletException {
- try {
- final Application application = getApplicationClass().newInstance();
- application.setRootPreserved(true);
- 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);
- }
- }
-
- /**
- * 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(WrappedPortletRequest request,
- WrappedPortletResponse 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, 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;
- }
-
- @Override
- 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(WrappedPortletRequest request,
- WrappedPortletResponse 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.getOutputStream();
- 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();
- }
-
- /**
- *
- * 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);
- }
-
- private static final Logger getLogger() {
- return Logger.getLogger(AbstractApplicationPortlet.class.getName());
- }
-
-}
diff --git a/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java b/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java
deleted file mode 100644
index 2ba19b0cf6..0000000000
--- a/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java
+++ /dev/null
@@ -1,1572 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-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.net.URL;
-import java.net.URLConnection;
-import java.security.GeneralSecurityException;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Enumeration;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Locale;
-import java.util.Properties;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
-import javax.servlet.ServletOutputStream;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
-
-import com.vaadin.Application;
-import com.vaadin.Application.ApplicationStartEvent;
-import com.vaadin.Application.SystemMessages;
-import com.vaadin.terminal.DeploymentConfiguration;
-import com.vaadin.terminal.Terminal;
-import com.vaadin.terminal.ThemeResource;
-import com.vaadin.terminal.WrappedRequest;
-import com.vaadin.terminal.WrappedResponse;
-import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.server.AbstractCommunicationManager.Callback;
-import com.vaadin.ui.Root;
-
-/**
- * Abstract implementation of the ApplicationServlet which handles all
- * communication between the client and the server.
- *
- * It is possible to extend this class to provide own functionality but in most
- * cases this is unnecessary.
- *
- *
- * @author Vaadin Ltd.
- * @version
- * @VERSION@
- * @since 6.0
- */
-
-@SuppressWarnings("serial")
-public abstract class AbstractApplicationServlet extends HttpServlet implements
- Constants {
-
- private static class AbstractApplicationServletWrapper implements Callback {
-
- private final AbstractApplicationServlet servlet;
-
- public AbstractApplicationServletWrapper(
- AbstractApplicationServlet servlet) {
- this.servlet = servlet;
- }
-
- @Override
- public void criticalNotification(WrappedRequest request,
- WrappedResponse response, String cap, String msg,
- String details, String outOfSyncURL) throws IOException {
- servlet.criticalNotification(
- WrappedHttpServletRequest.cast(request),
- ((WrappedHttpServletResponse) response), cap, msg, details,
- outOfSyncURL);
- }
- }
-
- // TODO Move some (all?) of the constants to a separate interface (shared
- // with portlet)
-
- private final String resourcePath = null;
-
- private DeploymentConfiguration deploymentConfiguration = new AbstractDeploymentConfiguration(
- getClass()) {
-
- @Override
- public String getStaticFileLocation(WrappedRequest request) {
- HttpServletRequest servletRequest = WrappedHttpServletRequest
- .cast(request);
- return AbstractApplicationServlet.this
- .getStaticFilesLocation(servletRequest);
- }
-
- @Override
- public String getConfiguredWidgetset(WrappedRequest request) {
- return getApplicationOrSystemProperty(
- AbstractApplicationServlet.PARAMETER_WIDGETSET,
- AbstractApplicationServlet.DEFAULT_WIDGETSET);
- }
-
- @Override
- public String getConfiguredTheme(WrappedRequest request) {
- // Use the default
- return AbstractApplicationServlet.getDefaultTheme();
- }
-
- @Override
- public boolean isStandalone(WrappedRequest request) {
- return true;
- }
-
- @Override
- public String getMimeType(String resourceName) {
- return getServletContext().getMimeType(resourceName);
- }
- };
-
- private final VaadinContext vaadinContext = new VaadinContext(
- getDeploymentConfiguration());
-
- /**
- * Called by the servlet container to indicate to a servlet that the servlet
- * is being placed into service.
- *
- * @param servletConfig
- * the object containing the servlet's configuration and
- * initialization parameters
- * @throws javax.servlet.ServletException
- * if an exception has occurred that interferes with the
- * servlet's normal operation.
- */
- @Override
- public void init(javax.servlet.ServletConfig servletConfig)
- throws javax.servlet.ServletException {
- super.init(servletConfig);
- Properties applicationProperties = getDeploymentConfiguration()
- .getInitParameters();
-
- // Read default parameters from server.xml
- final ServletContext context = servletConfig.getServletContext();
- for (final Enumeration<String> e = context.getInitParameterNames(); e
- .hasMoreElements();) {
- final String name = e.nextElement();
- applicationProperties.setProperty(name,
- context.getInitParameter(name));
- }
-
- // Override with application config from web.xml
- for (final Enumeration<String> e = servletConfig
- .getInitParameterNames(); e.hasMoreElements();) {
- final String name = e.nextElement();
- applicationProperties.setProperty(name,
- servletConfig.getInitParameter(name));
- }
-
- vaadinContext.init();
- }
-
- @Override
- public void destroy() {
- super.destroy();
-
- vaadinContext.destroy();
- }
-
- /**
- * 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 getDeploymentConfiguration().isProductionMode();
- }
-
- /**
- * Returns the number of seconds the browser should cache a file. Default is
- * 1 hour (3600 s).
- *
- * @return The number of seconds files are cached in the browser
- */
- public int getResourceCacheTime() {
- return getDeploymentConfiguration().getResourceCacheTime();
- }
-
- /**
- * Receives standard HTTP requests from the public service method and
- * dispatches them.
- *
- * @param request
- * the object that contains the request the client made of the
- * servlet.
- * @param response
- * the object that contains the response the servlet returns to
- * the client.
- * @throws ServletException
- * if an input or output error occurs while the servlet is
- * handling the TRACE request.
- * @throws IOException
- * if the request for the TRACE cannot be handled.
- */
-
- @Override
- protected void service(HttpServletRequest request,
- HttpServletResponse response) throws ServletException, IOException {
- service(createWrappedRequest(request), createWrappedResponse(response));
- }
-
- private void service(WrappedHttpServletRequest request,
- WrappedHttpServletResponse response) throws ServletException,
- IOException {
- RequestTimer requestTimer = new RequestTimer();
- requestTimer.start();
-
- AbstractApplicationServletWrapper servletWrapper = new AbstractApplicationServletWrapper(
- this);
-
- RequestType requestType = getRequestType(request);
- if (!ensureCookiesEnabled(requestType, request, response)) {
- return;
- }
-
- if (requestType == RequestType.STATIC_FILE) {
- serveStaticResources(request, response);
- return;
- }
-
- Application application = null;
- boolean transactionStarted = false;
- boolean requestStarted = false;
-
- try {
- // If a duplicate "close application" URL is received for an
- // application that is not open, redirect to the application's main
- // page.
- // This is needed as e.g. Spring Security remembers the last
- // URL from the application, which is the logout URL, and repeats
- // it.
- // We can tell apart a real onunload request from a repeated one
- // based on the real one having content (at least the UIDL security
- // key).
- if (requestType == RequestType.UIDL
- && request.getParameterMap().containsKey(
- ApplicationConnection.PARAM_UNLOADBURST)
- && request.getContentLength() < 1
- && getExistingApplication(request, false) == null) {
- redirectToApplication(request, response);
- return;
- }
-
- // Find out which application this request is related to
- application = findApplicationInstance(request, requestType);
- if (application == null) {
- return;
- }
- Application.setCurrent(application);
-
- /*
- * Get or create a WebApplicationContext and an ApplicationManager
- * for the session
- */
- WebApplicationContext webApplicationContext = getApplicationContext(request
- .getSession());
- CommunicationManager applicationManager = webApplicationContext
- .getApplicationManager(application, this);
-
- if (requestType == RequestType.CONNECTOR_RESOURCE) {
- applicationManager.serveConnectorResource(request, response);
- return;
- }
-
- /* Update browser information from the request */
- webApplicationContext.getBrowser().updateRequestDetails(request);
-
- /*
- * Call application requestStart before Application.init() is called
- * (bypasses the limitation in TransactionListener)
- */
- if (application instanceof HttpServletRequestListener) {
- ((HttpServletRequestListener) application).onRequestStart(
- request, response);
- requestStarted = true;
- }
-
- // Start the application if it's newly created
- startApplication(request, application, webApplicationContext);
-
- /*
- * Transaction starts. Call transaction listeners. Transaction end
- * is called in the finally block below.
- */
- webApplicationContext.startTransaction(application, request);
- transactionStarted = true;
-
- /* Handle the request */
- if (requestType == RequestType.FILE_UPLOAD) {
- // Root is resolved in communication manager
- applicationManager.handleFileUpload(application, request,
- response);
- return;
- } else if (requestType == RequestType.UIDL) {
- Root root = application.getRootForRequest(request);
- if (root == null) {
- throw new ServletException(ERROR_NO_ROOT_FOUND);
- }
- // Handles AJAX UIDL requests
- applicationManager.handleUidlRequest(request, response,
- servletWrapper, root);
- return;
- } else if (requestType == RequestType.BROWSER_DETAILS) {
- // Browser details - not related to a specific root
- applicationManager.handleBrowserDetailsRequest(request,
- response, application);
- return;
- }
-
- // Removes application if it has stopped (maybe by thread or
- // transactionlistener)
- if (!application.isRunning()) {
- endApplication(request, response, application);
- return;
- }
-
- if (applicationManager.handleApplicationRequest(request, response)) {
- return;
- }
- // TODO Should return 404 error here and not do anything more
-
- } catch (final SessionExpiredException e) {
- // Session has expired, notify user
- handleServiceSessionExpired(request, response);
- } catch (final GeneralSecurityException e) {
- handleServiceSecurityException(request, response);
- } catch (final Throwable e) {
- handleServiceException(request, response, application, e);
- } finally {
- // Notifies transaction end
- try {
- if (transactionStarted) {
- ((WebApplicationContext) application.getContext())
- .endTransaction(application, request);
-
- }
-
- } finally {
- try {
- if (requestStarted) {
- ((HttpServletRequestListener) application)
- .onRequestEnd(request, response);
- }
- } finally {
- Root.setCurrent(null);
- Application.setCurrent(null);
-
- HttpSession session = request.getSession(false);
- if (session != null) {
- requestTimer.stop(getApplicationContext(session));
- }
- }
- }
-
- }
- }
-
- private WrappedHttpServletResponse createWrappedResponse(
- HttpServletResponse response) {
- WrappedHttpServletResponse wrappedResponse = new WrappedHttpServletResponse(
- response, getDeploymentConfiguration());
- return wrappedResponse;
- }
-
- /**
- * Create a wrapped request for a http servlet request. This method can be
- * overridden if the wrapped request should have special properties.
- *
- * @param request
- * the original http servlet request
- * @return a wrapped request for the original request
- */
- protected WrappedHttpServletRequest createWrappedRequest(
- HttpServletRequest request) {
- return new WrappedHttpServletRequest(request,
- getDeploymentConfiguration());
- }
-
- /**
- * Gets a the deployment configuration for this servlet.
- *
- * @return the deployment configuration
- */
- protected DeploymentConfiguration getDeploymentConfiguration() {
- return deploymentConfiguration;
- }
-
- /**
- * Check that cookie support is enabled in the browser. Only checks UIDL
- * requests.
- *
- * @param requestType
- * Type of the request as returned by
- * {@link #getRequestType(HttpServletRequest)}
- * @param request
- * The request from the browser
- * @param response
- * The response to which an error can be written
- * @return false if cookies are disabled, true otherwise
- * @throws IOException
- */
- private boolean ensureCookiesEnabled(RequestType requestType,
- WrappedHttpServletRequest request,
- WrappedHttpServletResponse response) throws IOException {
- if (requestType == RequestType.UIDL && !isRepaintAll(request)) {
- // In all other but the first UIDL request a cookie should be
- // returned by the browser.
- // This can be removed if cookieless mode (#3228) is supported
- if (request.getRequestedSessionId() == null) {
- // User has cookies disabled
- criticalNotification(request, response, getSystemMessages()
- .getCookiesDisabledCaption(), getSystemMessages()
- .getCookiesDisabledMessage(), null, getSystemMessages()
- .getCookiesDisabledURL());
- return false;
- }
- }
- return true;
- }
-
- /**
- * Send a notification to client's application. Used to notify client of
- * critical errors, session expiration and more. Server has no knowledge of
- * what application client refers to.
- *
- * @param request
- * the HTTP request instance.
- * @param response
- * the HTTP response to write to.
- * @param caption
- * the notification caption
- * @param message
- * to notification body
- * @param details
- * a detail message to show in addition to the message. Currently
- * shown directly below the message but could be hidden behind a
- * details drop down in the future. Mainly used to give
- * additional information not necessarily useful to the end user.
- * @param url
- * url to load when the message is dismissed. Null will reload
- * the current page.
- * @throws IOException
- * if the writing failed due to input/output error.
- */
- protected void criticalNotification(WrappedHttpServletRequest request,
- HttpServletResponse response, String caption, String message,
- String details, String url) throws IOException {
-
- if (ServletPortletHelper.isUIDLRequest(request)) {
-
- if (caption != null) {
- caption = "\"" + JsonPaintTarget.escapeJSON(caption) + "\"";
- }
- if (details != null) {
- if (message == null) {
- message = details;
- } else {
- message += "<br/><br/>" + details;
- }
- }
-
- if (message != null) {
- message = "\"" + JsonPaintTarget.escapeJSON(message) + "\"";
- }
- if (url != null) {
- url = "\"" + JsonPaintTarget.escapeJSON(url) + "\"";
- }
-
- String output = "for(;;);[{\"changes\":[], \"meta\" : {"
- + "\"appError\": {" + "\"caption\":" + caption + ","
- + "\"message\" : " + message + "," + "\"url\" : " + url
- + "}}, \"resources\": {}, \"locales\":[]}]";
- writeResponse(response, "application/json; charset=UTF-8", output);
- } else {
- // Create an HTML reponse with the error
- String output = "";
-
- if (url != null) {
- output += "<a href=\"" + url + "\">";
- }
- if (caption != null) {
- output += "<b>" + caption + "</b><br/>";
- }
- if (message != null) {
- output += message;
- output += "<br/><br/>";
- }
-
- if (details != null) {
- output += details;
- output += "<br/><br/>";
- }
- if (url != null) {
- output += "</a>";
- }
- writeResponse(response, "text/html; charset=UTF-8", output);
-
- }
-
- }
-
- /**
- * Writes the response in {@code output} using the contentType given in
- * {@code contentType} to the provided {@link HttpServletResponse}
- *
- * @param response
- * @param contentType
- * @param output
- * Output to write (UTF-8 encoded)
- * @throws IOException
- */
- private void writeResponse(HttpServletResponse response,
- String contentType, String output) throws IOException {
- response.setContentType(contentType);
- final ServletOutputStream out = response.getOutputStream();
- // Set the response type
- final PrintWriter outWriter = new PrintWriter(new BufferedWriter(
- new OutputStreamWriter(out, "UTF-8")));
- outWriter.print(output);
- outWriter.flush();
- outWriter.close();
- out.flush();
-
- }
-
- /**
- * Returns the application instance to be used for the request. If an
- * existing instance is not found a new one is created or null is returned
- * to indicate that the application is not available.
- *
- * @param request
- * @param requestType
- * @return
- * @throws MalformedURLException
- * @throws IllegalAccessException
- * @throws InstantiationException
- * @throws ServletException
- * @throws SessionExpiredException
- */
- private Application findApplicationInstance(HttpServletRequest request,
- RequestType requestType) throws MalformedURLException,
- ServletException, SessionExpiredException {
-
- 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 = (request
- .getParameter(URL_PARAMETER_RESTART_APPLICATION) != null);
- final boolean closeApplication = (request
- .getParameter(URL_PARAMETER_CLOSE_APPLICATION) != null);
-
- if (restartApplication) {
- closeApplication(application, request.getSession(false));
- return createApplication(request);
- } else if (closeApplication) {
- closeApplication(application, request.getSession(false));
- return null;
- } else {
- return application;
- }
- }
-
- // No existing application was found
-
- if (requestCanCreateApplication) {
- /*
- * If the request is such that it should create a new application if
- * one as not found, we do that.
- */
- return createApplication(request);
- } else {
- /*
- * The application was not found and a new one should not be
- * created. Assume the session has expired.
- */
- throw new SessionExpiredException();
- }
-
- }
-
- /**
- * Check if the request should create an application if an existing
- * application is not found.
- *
- * @param request
- * @param requestType
- * @return true if an application should be created, false otherwise
- */
- boolean requestCanCreateApplication(HttpServletRequest request,
- RequestType requestType) {
- if (requestType == RequestType.UIDL && isRepaintAll(request)) {
- /*
- * UIDL request contains valid repaintAll=1 event, the user probably
- * wants to initiate a new application through a custom index.html
- * without using the bootstrap page.
- */
- return true;
-
- } else if (requestType == RequestType.OTHER) {
- /*
- * I.e URIs that are not application resources or static (theme)
- * files.
- */
- return true;
-
- }
-
- return false;
- }
-
- /**
- * Gets resource path using different implementations. Required to
- * supporting different servlet container implementations (application
- * servers).
- *
- * @param servletContext
- * @param path
- * the resource path.
- * @return the resource path.
- */
- protected static String getResourcePath(ServletContext servletContext,
- String path) {
- String resultPath = null;
- resultPath = servletContext.getRealPath(path);
- if (resultPath != null) {
- return resultPath;
- } else {
- try {
- final URL url = servletContext.getResource(path);
- resultPath = url.getFile();
- } catch (final Exception e) {
- // FIXME: Handle exception
- getLogger().log(Level.INFO,
- "Could not find resource path " + path, e);
- }
- }
- return resultPath;
- }
-
- /**
- * Creates a new application and registers it into WebApplicationContext
- * (aka session). This is not meant to be overridden. Override
- * getNewApplication to create the application instance in a custom way.
- *
- * @param request
- * @return
- * @throws ServletException
- * @throws MalformedURLException
- */
- private Application createApplication(HttpServletRequest request)
- throws ServletException, MalformedURLException {
- Application newApplication = getNewApplication(request);
-
- final WebApplicationContext context = getApplicationContext(request
- .getSession());
- context.addApplication(newApplication);
-
- return newApplication;
- }
-
- private void handleServiceException(WrappedHttpServletRequest request,
- WrappedHttpServletResponse response, Application application,
- Throwable e) throws IOException, ServletException {
- // if this was an UIDL request, response UIDL back to client
- if (getRequestType(request) == RequestType.UIDL) {
- Application.SystemMessages ci = getSystemMessages();
- criticalNotification(request, response,
- ci.getInternalErrorCaption(), ci.getInternalErrorMessage(),
- null, ci.getInternalErrorURL());
- if (application != null) {
- application.getErrorHandler()
- .terminalError(new RequestError(e));
- } else {
- throw new ServletException(e);
- }
- } else {
- // Re-throw other exceptions
- throw new ServletException(e);
- }
-
- }
-
- /**
- * A helper method to strip away characters that might somehow be used for
- * XSS attacs. Leaves at least alphanumeric characters intact. Also removes
- * eg. ( and ), so values should be safe in javascript too.
- *
- * @param themeName
- * @return
- */
- protected static String stripSpecialChars(String themeName) {
- StringBuilder sb = new StringBuilder();
- char[] charArray = themeName.toCharArray();
- for (int i = 0; i < charArray.length; i++) {
- char c = charArray[i];
- if (!CHAR_BLACKLIST.contains(c)) {
- sb.append(c);
- }
- }
- return sb.toString();
- }
-
- private static final Collection<Character> CHAR_BLACKLIST = new HashSet<Character>(
- Arrays.asList(new Character[] { '&', '"', '\'', '<', '>', '(', ')',
- ';' }));
-
- /**
- * Returns the default theme. Must never return null.
- *
- * @return
- */
- public static String getDefaultTheme() {
- return DEFAULT_THEME_NAME;
- }
-
- void handleServiceSessionExpired(WrappedHttpServletRequest request,
- WrappedHttpServletResponse response) throws IOException,
- ServletException {
-
- if (isOnUnloadRequest(request)) {
- /*
- * Request was an unload request (e.g. window close event) and the
- * client expects no response if it fails.
- */
- return;
- }
-
- try {
- Application.SystemMessages ci = getSystemMessages();
- if (getRequestType(request) != RequestType.UIDL) {
- // 'plain' http req - e.g. browser reload;
- // just go ahead redirect the browser
- response.sendRedirect(ci.getSessionExpiredURL());
- } else {
- /*
- * Invalidate session (weird to have session if we're saying
- * that it's expired, and worse: portal integration will fail
- * since the session is not created by the portal.
- *
- * Session must be invalidated before criticalNotification as it
- * commits the response.
- */
- request.getSession().invalidate();
-
- // send uidl redirect
- criticalNotification(request, response,
- ci.getSessionExpiredCaption(),
- ci.getSessionExpiredMessage(), null,
- ci.getSessionExpiredURL());
-
- }
- } catch (SystemMessageException ee) {
- throw new ServletException(ee);
- }
-
- }
-
- private void handleServiceSecurityException(
- WrappedHttpServletRequest request,
- WrappedHttpServletResponse response) throws IOException,
- ServletException {
- if (isOnUnloadRequest(request)) {
- /*
- * Request was an unload request (e.g. window close event) and the
- * client expects no response if it fails.
- */
- return;
- }
-
- try {
- Application.SystemMessages ci = getSystemMessages();
- if (getRequestType(request) != RequestType.UIDL) {
- // 'plain' http req - e.g. browser reload;
- // just go ahead redirect the browser
- response.sendRedirect(ci.getCommunicationErrorURL());
- } else {
- // send uidl redirect
- criticalNotification(request, response,
- ci.getCommunicationErrorCaption(),
- ci.getCommunicationErrorMessage(),
- INVALID_SECURITY_KEY_MSG, ci.getCommunicationErrorURL());
- /*
- * Invalidate session. Portal integration will fail otherwise
- * since the session is not created by the portal.
- */
- request.getSession().invalidate();
- }
- } catch (SystemMessageException ee) {
- throw new ServletException(ee);
- }
-
- log("Invalid security key received from " + request.getRemoteHost());
- }
-
- /**
- * Creates a new application for the given request.
- *
- * @param request
- * the HTTP request.
- * @return A new Application instance.
- * @throws ServletException
- */
- protected abstract Application getNewApplication(HttpServletRequest request)
- throws ServletException;
-
- /**
- * Starts the application if it is not already running.
- *
- * @param request
- * @param application
- * @param webApplicationContext
- * @throws ServletException
- * @throws MalformedURLException
- */
- private void startApplication(HttpServletRequest request,
- Application application, WebApplicationContext webApplicationContext)
- throws ServletException, MalformedURLException {
-
- if (!application.isRunning()) {
- // Create application
- final URL applicationUrl = getApplicationUrl(request);
-
- // Initial locale comes from the request
- Locale locale = request.getLocale();
- application.setLocale(locale);
- application.start(new ApplicationStartEvent(applicationUrl,
- getDeploymentConfiguration(), webApplicationContext));
- }
- }
-
- /**
- * Check if this is a request for a static resource and, if it is, serve the
- * resource to the client.
- *
- * @param request
- * @param response
- * @return true if a file was served and the request has been handled, false
- * otherwise.
- * @throws IOException
- * @throws ServletException
- */
- private boolean serveStaticResources(HttpServletRequest request,
- HttpServletResponse response) throws IOException, ServletException {
-
- // FIXME What does 10 refer to?
- String pathInfo = request.getPathInfo();
- if (pathInfo == null || pathInfo.length() <= 10) {
- return false;
- }
-
- if ((request.getContextPath() != null)
- && (request.getRequestURI().startsWith("/VAADIN/"))) {
- serveStaticResourcesInVAADIN(request.getRequestURI(), request,
- response);
- return true;
- } else if (request.getRequestURI().startsWith(
- request.getContextPath() + "/VAADIN/")) {
- serveStaticResourcesInVAADIN(
- request.getRequestURI().substring(
- request.getContextPath().length()), request,
- response);
- return true;
- }
-
- return false;
- }
-
- /**
- * Serve resources from VAADIN directory.
- *
- * @param filename
- * The filename to serve. Should always start with /VAADIN/.
- * @param request
- * @param response
- * @throws IOException
- * @throws ServletException
- */
- private void serveStaticResourcesInVAADIN(String filename,
- HttpServletRequest request, HttpServletResponse response)
- throws IOException, ServletException {
-
- final ServletContext sc = getServletContext();
- URL resourceUrl = sc.getResource(filename);
- if (resourceUrl == null) {
- // try if requested file is found from classloader
-
- // strip leading "/" otherwise stream from JAR wont work
- filename = filename.substring(1);
- resourceUrl = getDeploymentConfiguration().getClassLoader()
- .getResource(filename);
-
- if (resourceUrl == null) {
- // cannot serve requested file
- getLogger()
- .info("Requested resource ["
- + filename
- + "] not found from filesystem or through class loader."
- + " Add widgetset and/or theme JAR to your classpath or add files to WebContent/VAADIN folder.");
- response.setStatus(HttpServletResponse.SC_NOT_FOUND);
- return;
- }
-
- // security check: do not permit navigation out of the VAADIN
- // directory
- if (!isAllowedVAADINResourceUrl(request, resourceUrl)) {
- getLogger()
- .info("Requested resource ["
- + filename
- + "] not accessible in the VAADIN directory or access to it is forbidden.");
- response.setStatus(HttpServletResponse.SC_FORBIDDEN);
- return;
- }
- }
-
- // Find the modification timestamp
- long lastModifiedTime = 0;
- URLConnection connection = null;
- try {
- connection = resourceUrl.openConnection();
- lastModifiedTime = connection.getLastModified();
- // Remove milliseconds to avoid comparison problems (milliseconds
- // are not returned by the browser in the "If-Modified-Since"
- // header).
- lastModifiedTime = lastModifiedTime - lastModifiedTime % 1000;
-
- if (browserHasNewestVersion(request, lastModifiedTime)) {
- response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
- return;
- }
- } catch (Exception e) {
- // Failed to find out last modified timestamp. Continue without it.
- getLogger()
- .log(Level.FINEST,
- "Failed to find out last modified timestamp. Continuing without it.",
- e);
- } finally {
- if (connection instanceof URLConnection) {
- try {
- // Explicitly close the input stream to prevent it
- // from remaining hanging
- // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4257700
- InputStream is = connection.getInputStream();
- if (is != null) {
- is.close();
- }
- } catch (IOException e) {
- getLogger().log(Level.INFO,
- "Error closing URLConnection input stream", e);
- }
- }
- }
-
- // Set type mime type if we can determine it based on the filename
- final String mimetype = sc.getMimeType(filename);
- if (mimetype != null) {
- response.setContentType(mimetype);
- }
-
- // Provide modification timestamp to the browser if it is known.
- if (lastModifiedTime > 0) {
- response.setDateHeader("Last-Modified", lastModifiedTime);
- /*
- * The browser is allowed to cache for 1 hour without checking if
- * the file has changed. This forces browsers to fetch a new version
- * when the Vaadin version is updated. This will cause more requests
- * to the servlet than without this but for high volume sites the
- * static files should never be served through the servlet. The
- * cache timeout can be configured by setting the resourceCacheTime
- * parameter in web.xml
- */
- response.setHeader("Cache-Control",
- "max-age= " + String.valueOf(getResourceCacheTime()));
- }
-
- // Write the resource to the client.
- final OutputStream os = response.getOutputStream();
- final byte buffer[] = new byte[DEFAULT_BUFFER_SIZE];
- int bytes;
- InputStream is = resourceUrl.openStream();
- while ((bytes = is.read(buffer)) >= 0) {
- os.write(buffer, 0, bytes);
- }
- is.close();
- }
-
- /**
- * Check whether a URL obtained from a classloader refers to a valid static
- * resource in the directory VAADIN.
- *
- * Warning: Overriding of this method is not recommended, but is possible to
- * support non-default classloaders or servers that may produce URLs
- * different from the normal ones. The method prototype may change in the
- * future. Care should be taken not to expose class files or other resources
- * outside the VAADIN directory if the method is overridden.
- *
- * @param request
- * @param resourceUrl
- * @return
- *
- * @since 6.6.7
- */
- protected boolean isAllowedVAADINResourceUrl(HttpServletRequest request,
- URL resourceUrl) {
- if ("jar".equals(resourceUrl.getProtocol())) {
- // This branch is used for accessing resources directly from the
- // Vaadin JAR in development environments and in similar cases.
-
- // Inside a JAR, a ".." would mean a real directory named ".." so
- // using it in paths should just result in the file not being found.
- // However, performing a check in case some servers or class loaders
- // try to normalize the path by collapsing ".." before the class
- // loader sees it.
-
- if (!resourceUrl.getPath().contains("!/VAADIN/")) {
- getLogger().info(
- "Blocked attempt to access a JAR entry not starting with /VAADIN/: "
- + resourceUrl);
- return false;
- }
- getLogger().fine(
- "Accepted access to a JAR entry using a class loader: "
- + resourceUrl);
- return true;
- } else {
- // Some servers such as GlassFish extract files from JARs (file:)
- // and e.g. JBoss 5+ use protocols vsf: and vfsfile: .
-
- // Check that the URL is in a VAADIN directory and does not contain
- // "/../"
- if (!resourceUrl.getPath().contains("/VAADIN/")
- || resourceUrl.getPath().contains("/../")) {
- getLogger().info(
- "Blocked attempt to access file: " + resourceUrl);
- return false;
- }
- getLogger().fine(
- "Accepted access to a file using a class loader: "
- + resourceUrl);
- return true;
- }
- }
-
- /**
- * Checks if the browser has an up to date cached version of requested
- * resource. Currently the check is performed using the "If-Modified-Since"
- * header. Could be expanded if needed.
- *
- * @param request
- * The HttpServletRequest from the browser.
- * @param resourceLastModifiedTimestamp
- * The timestamp when the resource was last modified. 0 if the
- * last modification time is unknown.
- * @return true if the If-Modified-Since header tells the cached version in
- * the browser is up to date, false otherwise
- */
- private boolean browserHasNewestVersion(HttpServletRequest request,
- long resourceLastModifiedTimestamp) {
- if (resourceLastModifiedTimestamp < 1) {
- // We do not know when it was modified so the browser cannot have an
- // up-to-date version
- return false;
- }
- /*
- * The browser can request the resource conditionally using an
- * If-Modified-Since header. Check this against the last modification
- * time.
- */
- try {
- // If-Modified-Since represents the timestamp of the version cached
- // in the browser
- long headerIfModifiedSince = request
- .getDateHeader("If-Modified-Since");
-
- if (headerIfModifiedSince >= resourceLastModifiedTimestamp) {
- // Browser has this an up-to-date version of the resource
- return true;
- }
- } catch (Exception e) {
- // Failed to parse header. Fail silently - the browser does not have
- // an up-to-date version in its cache.
- }
- return false;
- }
-
- protected enum RequestType {
- FILE_UPLOAD, BROWSER_DETAILS, UIDL, OTHER, STATIC_FILE, APPLICATION_RESOURCE, CONNECTOR_RESOURCE;
- }
-
- protected RequestType getRequestType(WrappedHttpServletRequest request) {
- if (ServletPortletHelper.isFileUploadRequest(request)) {
- return RequestType.FILE_UPLOAD;
- } else if (ServletPortletHelper.isConnectorResourceRequest(request)) {
- return RequestType.CONNECTOR_RESOURCE;
- } else if (isBrowserDetailsRequest(request)) {
- return RequestType.BROWSER_DETAILS;
- } else if (ServletPortletHelper.isUIDLRequest(request)) {
- return RequestType.UIDL;
- } else if (isStaticResourceRequest(request)) {
- return RequestType.STATIC_FILE;
- } else if (ServletPortletHelper.isApplicationResourceRequest(request)) {
- return RequestType.APPLICATION_RESOURCE;
- }
- return RequestType.OTHER;
-
- }
-
- private static boolean isBrowserDetailsRequest(HttpServletRequest request) {
- return "POST".equals(request.getMethod())
- && request.getParameter("browserDetails") != null;
- }
-
- private boolean isStaticResourceRequest(HttpServletRequest request) {
- String pathInfo = request.getPathInfo();
- if (pathInfo == null || pathInfo.length() <= 10) {
- return false;
- }
-
- if ((request.getContextPath() != null)
- && (request.getRequestURI().startsWith("/VAADIN/"))) {
- return true;
- } else if (request.getRequestURI().startsWith(
- request.getContextPath() + "/VAADIN/")) {
- return true;
- }
-
- return false;
- }
-
- private boolean isOnUnloadRequest(HttpServletRequest request) {
- return request.getParameter(ApplicationConnection.PARAM_UNLOADBURST) != null;
- }
-
- /**
- * Get system messages from the current application class
- *
- * @return
- */
- protected SystemMessages getSystemMessages() {
- Class<? extends Application> appCls = null;
- try {
- appCls = getApplicationClass();
- } catch (ClassNotFoundException e) {
- // Previous comment claimed that this should never happen
- throw new SystemMessageException(e);
- }
- return getSystemMessages(appCls);
- }
-
- public static SystemMessages getSystemMessages(
- Class<? extends Application> appCls) {
- try {
- if (appCls != null) {
- Method m = appCls
- .getMethod("getSystemMessages", (Class[]) null);
- return (Application.SystemMessages) m.invoke(null,
- (Object[]) null);
- }
- } catch (SecurityException e) {
- throw new SystemMessageException(
- "Application.getSystemMessage() should be static public", e);
- } 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();
- }
-
- protected abstract Class<? extends Application> getApplicationClass()
- throws ClassNotFoundException;
-
- /**
- * 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.
- *
- * The returned folder is usually the same as the context path and
- * independent of the application.
- *
- * @param request
- * @return The location of static resources (should contain the VAADIN
- * directory). Never ends with a slash (/).
- */
- protected String getStaticFilesLocation(HttpServletRequest request) {
-
- return getWebApplicationsStaticFileLocation(request);
- }
-
- /**
- * The default method to fetch static files location (URL). This method does
- * not check for request attribute {@value #REQUEST_VAADIN_STATIC_FILE_PATH}
- *
- * @param request
- * @return
- */
- private String getWebApplicationsStaticFileLocation(
- HttpServletRequest request) {
- String staticFileLocation;
- // if property is defined in configurations, use that
- staticFileLocation = getDeploymentConfiguration()
- .getApplicationOrSystemProperty(PARAMETER_VAADIN_RESOURCES,
- null);
- if (staticFileLocation != null) {
- return staticFileLocation;
- }
-
- // the last (but most common) option is to generate default location
- // from request
-
- // if context is specified add it to widgetsetUrl
- String ctxPath = request.getContextPath();
-
- // FIXME: ctxPath.length() == 0 condition is probably unnecessary and
- // might even be wrong.
-
- if (ctxPath.length() == 0
- && request.getAttribute("javax.servlet.include.context_path") != null) {
- // include request (e.g portlet), get context path from
- // attribute
- ctxPath = (String) request
- .getAttribute("javax.servlet.include.context_path");
- }
-
- // Remove heading and trailing slashes from the context path
- ctxPath = removeHeadingOrTrailing(ctxPath, "/");
-
- if (ctxPath.equals("")) {
- return "";
- } else {
- return "/" + ctxPath;
- }
- }
-
- /**
- * Remove any heading or trailing "what" from the "string".
- *
- * @param string
- * @param what
- * @return
- */
- private static String removeHeadingOrTrailing(String string, String what) {
- while (string.startsWith(what)) {
- string = string.substring(1);
- }
-
- while (string.endsWith(what)) {
- string = string.substring(0, string.length() - 1);
- }
-
- return string;
- }
-
- /**
- * Write a redirect response to the main page of the application.
- *
- * @param request
- * @param response
- * @throws IOException
- * if sending the redirect fails due to an input/output error or
- * a bad application URL
- */
- private void redirectToApplication(HttpServletRequest request,
- HttpServletResponse response) throws IOException {
- String applicationUrl = getApplicationUrl(request).toExternalForm();
- response.sendRedirect(response.encodeRedirectURL(applicationUrl));
- }
-
- /**
- * Gets the current application URL from request.
- *
- * @param request
- * the HTTP request.
- * @throws MalformedURLException
- * if the application is denied access to the persistent data
- * store represented by the given URL.
- */
- protected URL getApplicationUrl(HttpServletRequest request)
- throws MalformedURLException {
- final URL reqURL = new URL(
- (request.isSecure() ? "https://" : "http://")
- + request.getServerName()
- + ((request.isSecure() && request.getServerPort() == 443)
- || (!request.isSecure() && request
- .getServerPort() == 80) ? "" : ":"
- + request.getServerPort())
- + request.getRequestURI());
- String servletPath = "";
- if (request.getAttribute("javax.servlet.include.servlet_path") != null) {
- // this is an include request
- servletPath = request.getAttribute(
- "javax.servlet.include.context_path").toString()
- + request
- .getAttribute("javax.servlet.include.servlet_path");
-
- } else {
- servletPath = request.getContextPath() + request.getServletPath();
- }
-
- if (servletPath.length() == 0
- || servletPath.charAt(servletPath.length() - 1) != '/') {
- servletPath = servletPath + "/";
- }
- URL u = new URL(reqURL, servletPath);
- return u;
- }
-
- /**
- * Gets the existing application for given request. Looks for application
- * instance for given request based on the requested URL.
- *
- * @param request
- * the HTTP request.
- * @param allowSessionCreation
- * true if a session should be created if no session exists,
- * false if no session should be created
- * @return Application instance, or null if the URL does not map to valid
- * application.
- * @throws MalformedURLException
- * if the application is denied access to the persistent data
- * store represented by the given URL.
- * @throws IllegalAccessException
- * @throws InstantiationException
- * @throws SessionExpiredException
- */
- protected Application getExistingApplication(HttpServletRequest request,
- boolean allowSessionCreation) throws MalformedURLException,
- SessionExpiredException {
-
- // Ensures that the session is still valid
- final HttpSession session = request.getSession(allowSessionCreation);
- if (session == null) {
- throw new SessionExpiredException();
- }
-
- WebApplicationContext context = getApplicationContext(session);
-
- // Gets application list for the session.
- final Collection<Application> applications = context.getApplications();
-
- // Search for the application (using the application URI) from the list
- for (final Iterator<Application> i = applications.iterator(); i
- .hasNext();) {
- final Application sessionApplication = i.next();
- final String sessionApplicationPath = sessionApplication.getURL()
- .getPath();
- String requestApplicationPath = getApplicationUrl(request)
- .getPath();
-
- if (requestApplicationPath.equals(sessionApplicationPath)) {
- // Found a running application
- if (sessionApplication.isRunning()) {
- return sessionApplication;
- }
- // Application has stopped, so remove it before creating a new
- // application
- getApplicationContext(session).removeApplication(
- sessionApplication);
- break;
- }
- }
-
- // Existing application not found
- return null;
- }
-
- /**
- * Ends the application.
- *
- * @param request
- * the HTTP request.
- * @param response
- * the HTTP response to write to.
- * @param application
- * the application to end.
- * @throws IOException
- * if the writing failed due to input/output error.
- */
- private void endApplication(HttpServletRequest request,
- HttpServletResponse response, Application application)
- throws IOException {
-
- String logoutUrl = application.getLogoutURL();
- if (logoutUrl == null) {
- logoutUrl = application.getURL().toString();
- }
-
- final HttpSession session = request.getSession();
- if (session != null) {
- getApplicationContext(session).removeApplication(application);
- }
-
- response.sendRedirect(response.encodeRedirectURL(logoutUrl));
- }
-
- /**
- * Returns the path info; note that this _can_ be different than
- * request.getPathInfo(). Examples where this might be useful:
- * <ul>
- * <li>An application runner servlet that runs different Vaadin applications
- * based on an identifier.</li>
- * <li>Providing a REST interface in the context root, while serving a
- * Vaadin UI on a sub-URI using only one servlet (e.g. REST on
- * http://example.com/foo, UI on http://example.com/foo/vaadin)</li>
- *
- * @param request
- * @return
- */
- protected String getRequestPathInfo(HttpServletRequest request) {
- return request.getPathInfo();
- }
-
- /**
- * Gets relative location of a theme resource.
- *
- * @param theme
- * the Theme name.
- * @param resource
- * the Theme resource.
- * @return External URI specifying the resource
- */
- public String getResourceLocation(String theme, ThemeResource resource) {
-
- if (resourcePath == null) {
- return resource.getResourceId();
- }
- return resourcePath + theme + "/" + resource.getResourceId();
- }
-
- private boolean isRepaintAll(HttpServletRequest request) {
- return (request.getParameter(URL_PARAMETER_REPAINT_ALL) != null)
- && (request.getParameter(URL_PARAMETER_REPAINT_ALL).equals("1"));
- }
-
- private void closeApplication(Application application, HttpSession session) {
- if (application == null) {
- return;
- }
-
- application.close();
- if (session != null) {
- WebApplicationContext context = getApplicationContext(session);
- context.removeApplication(application);
- }
- }
-
- /**
- *
- * Gets the application context from an HttpSession. If no context is
- * currently stored in a session a new context is created and stored in the
- * session.
- *
- * @param session
- * the HTTP session.
- * @return the application context for HttpSession.
- */
- protected WebApplicationContext getApplicationContext(HttpSession session) {
- /*
- * TODO the ApplicationContext.getApplicationContext() should be removed
- * and logic moved here. Now overriding context type is possible, but
- * the whole creation logic should be here. MT 1101
- */
- return WebApplicationContext.getApplicationContext(session);
- }
-
- public class RequestError implements Terminal.ErrorEvent, Serializable {
-
- private final Throwable throwable;
-
- public RequestError(Throwable throwable) {
- this.throwable = throwable;
- }
-
- @Override
- public Throwable getThrowable() {
- return throwable;
- }
-
- }
-
- /**
- * Override this method if you need to use a specialized communicaiton
- * mananger implementation.
- *
- * @deprecated Instead of overriding this method, override
- * {@link WebApplicationContext} implementation via
- * {@link AbstractApplicationServlet#getApplicationContext(HttpSession)}
- * method and in that customized implementation return your
- * CommunicationManager in
- * {@link WebApplicationContext#getApplicationManager(Application, AbstractApplicationServlet)}
- * method.
- *
- * @param application
- * @return
- */
- @Deprecated
- public CommunicationManager createCommunicationManager(
- Application application) {
- return new CommunicationManager(application);
- }
-
- /**
- * Escapes characters to html entities. An exception is made for some
- * "safe characters" to keep the text somewhat readable.
- *
- * @param unsafe
- * @return a safe string to be added inside an html tag
- */
- public static final String safeEscapeForHtml(String unsafe) {
- if (null == unsafe) {
- return null;
- }
- StringBuilder safe = new StringBuilder();
- char[] charArray = unsafe.toCharArray();
- for (int i = 0; i < charArray.length; i++) {
- char c = charArray[i];
- if (isSafe(c)) {
- safe.append(c);
- } else {
- safe.append("&#");
- safe.append((int) c);
- safe.append(";");
- }
- }
-
- return safe.toString();
- }
-
- private static boolean isSafe(char c) {
- return //
- c > 47 && c < 58 || // alphanum
- c > 64 && c < 91 || // A-Z
- c > 96 && c < 123 // a-z
- ;
- }
-
- private static final Logger getLogger() {
- return Logger.getLogger(AbstractApplicationServlet.class.getName());
- }
-}
diff --git a/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java b/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java
deleted file mode 100644
index b87aaa278b..0000000000
--- a/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java
+++ /dev/null
@@ -1,2791 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal.gwt.server;
-
-import java.io.BufferedWriter;
-import java.io.ByteArrayOutputStream;
-import java.io.CharArrayWriter;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.PrintWriter;
-import java.io.Serializable;
-import java.io.StringWriter;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Type;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.security.GeneralSecurityException;
-import java.text.CharacterIterator;
-import java.text.DateFormat;
-import java.text.DateFormatSymbols;
-import java.text.SimpleDateFormat;
-import java.text.StringCharacterIterator;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.GregorianCalendar;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Set;
-import java.util.UUID;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import javax.servlet.http.HttpServletResponse;
-
-import com.vaadin.Application;
-import com.vaadin.Application.SystemMessages;
-import com.vaadin.RootRequiresMoreInformationException;
-import com.vaadin.Version;
-import com.vaadin.annotations.JavaScript;
-import com.vaadin.annotations.StyleSheet;
-import com.vaadin.external.json.JSONArray;
-import com.vaadin.external.json.JSONException;
-import com.vaadin.external.json.JSONObject;
-import com.vaadin.shared.Connector;
-import com.vaadin.shared.communication.MethodInvocation;
-import com.vaadin.shared.communication.SharedState;
-import com.vaadin.shared.communication.UidlValue;
-import com.vaadin.terminal.AbstractClientConnector;
-import com.vaadin.terminal.CombinedRequest;
-import com.vaadin.terminal.LegacyPaint;
-import com.vaadin.terminal.PaintException;
-import com.vaadin.terminal.PaintTarget;
-import com.vaadin.terminal.RequestHandler;
-import com.vaadin.terminal.StreamVariable;
-import com.vaadin.terminal.StreamVariable.StreamingEndEvent;
-import com.vaadin.terminal.StreamVariable.StreamingErrorEvent;
-import com.vaadin.terminal.Terminal.ErrorEvent;
-import com.vaadin.terminal.Terminal.ErrorListener;
-import com.vaadin.terminal.Vaadin6Component;
-import com.vaadin.terminal.VariableOwner;
-import com.vaadin.terminal.WrappedRequest;
-import com.vaadin.terminal.WrappedResponse;
-import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.server.BootstrapHandler.BootstrapContext;
-import com.vaadin.terminal.gwt.server.ComponentSizeValidator.InvalidLayout;
-import com.vaadin.terminal.gwt.server.RpcManager.RpcInvocationException;
-import com.vaadin.ui.AbstractComponent;
-import com.vaadin.ui.AbstractField;
-import com.vaadin.ui.Component;
-import com.vaadin.ui.ConnectorTracker;
-import com.vaadin.ui.HasComponents;
-import com.vaadin.ui.Root;
-import com.vaadin.ui.Window;
-
-/**
- * This is a common base class for the server-side implementations of the
- * communication system between the client code (compiled with GWT into
- * JavaScript) and the server side components. Its client side counterpart is
- * {@link ApplicationConnection}.
- *
- * TODO Document better!
- */
-@SuppressWarnings("serial")
-public abstract class AbstractCommunicationManager implements Serializable {
-
- private static final String DASHDASH = "--";
-
- private static final RequestHandler APP_RESOURCE_HANDLER = new ApplicationResourceHandler();
-
- private static final RequestHandler UNSUPPORTED_BROWSER_HANDLER = new UnsupportedBrowserHandler();
-
- /**
- * TODO Document me!
- *
- * @author peholmst
- */
- public interface Callback extends Serializable {
-
- public void criticalNotification(WrappedRequest request,
- WrappedResponse response, String cap, String msg,
- String details, String outOfSyncURL) throws IOException;
- }
-
- static class UploadInterruptedException extends Exception {
- public UploadInterruptedException() {
- super("Upload interrupted by other thread");
- }
- }
-
- private static String GET_PARAM_REPAINT_ALL = "repaintAll";
-
- // flag used in the request to indicate that the security token should be
- // written to the response
- private static final String WRITE_SECURITY_TOKEN_FLAG = "writeSecurityToken";
-
- /* Variable records indexes */
- public static final char VAR_BURST_SEPARATOR = '\u001d';
-
- public static final char VAR_ESCAPE_CHARACTER = '\u001b';
-
- private final HashMap<Integer, ClientCache> rootToClientCache = new HashMap<Integer, ClientCache>();
-
- private static final int MAX_BUFFER_SIZE = 64 * 1024;
-
- /* Same as in apache commons file upload library that was previously used. */
- private static final int MAX_UPLOAD_BUFFER_SIZE = 4 * 1024;
-
- private static final String GET_PARAM_ANALYZE_LAYOUTS = "analyzeLayouts";
-
- /**
- * The application this communication manager is used for
- */
- private final Application application;
-
- private List<String> locales;
-
- private int pendingLocalesIndex;
-
- private int timeoutInterval = -1;
-
- private DragAndDropService dragAndDropService;
-
- private String requestThemeName;
-
- private int maxInactiveInterval;
-
- private Connector highlightedConnector;
-
- private Map<String, Class<?>> connectorResourceContexts = new HashMap<String, Class<?>>();
-
- private Map<String, Map<String, StreamVariable>> pidToNameToStreamVariable;
-
- private Map<StreamVariable, String> streamVariableToSeckey;
-
- /**
- * TODO New constructor - document me!
- *
- * @param application
- */
- public AbstractCommunicationManager(Application application) {
- this.application = application;
- application.addRequestHandler(getBootstrapHandler());
- application.addRequestHandler(APP_RESOURCE_HANDLER);
- application.addRequestHandler(UNSUPPORTED_BROWSER_HANDLER);
- requireLocale(application.getLocale().toString());
- }
-
- protected Application getApplication() {
- return application;
- }
-
- private static final int LF = "\n".getBytes()[0];
-
- private static final String CRLF = "\r\n";
-
- private static final String UTF8 = "UTF8";
-
- private static final String GET_PARAM_HIGHLIGHT_COMPONENT = "highlightComponent";
-
- private static String readLine(InputStream stream) throws IOException {
- ByteArrayOutputStream bout = new ByteArrayOutputStream();
- int readByte = stream.read();
- while (readByte != LF) {
- bout.write(readByte);
- readByte = stream.read();
- }
- byte[] bytes = bout.toByteArray();
- return new String(bytes, 0, bytes.length - 1, UTF8);
- }
-
- /**
- * Method used to stream content from a multipart request (either from
- * servlet or portlet request) to given StreamVariable
- *
- *
- * @param request
- * @param response
- * @param streamVariable
- * @param owner
- * @param boundary
- * @throws IOException
- */
- protected void doHandleSimpleMultipartFileUpload(WrappedRequest request,
- WrappedResponse response, StreamVariable streamVariable,
- String variableName, ClientConnector owner, String boundary)
- throws IOException {
- // multipart parsing, supports only one file for request, but that is
- // fine for our current terminal
-
- final InputStream inputStream = request.getInputStream();
-
- int contentLength = request.getContentLength();
-
- boolean atStart = false;
- boolean firstFileFieldFound = false;
-
- String rawfilename = "unknown";
- String rawMimeType = "application/octet-stream";
-
- /*
- * Read the stream until the actual file starts (empty line). Read
- * filename and content type from multipart headers.
- */
- while (!atStart) {
- String readLine = readLine(inputStream);
- contentLength -= (readLine.length() + 2);
- if (readLine.startsWith("Content-Disposition:")
- && readLine.indexOf("filename=") > 0) {
- rawfilename = readLine.replaceAll(".*filename=", "");
- String parenthesis = rawfilename.substring(0, 1);
- rawfilename = rawfilename.substring(1);
- rawfilename = rawfilename.substring(0,
- rawfilename.indexOf(parenthesis));
- firstFileFieldFound = true;
- } else if (firstFileFieldFound && readLine.equals("")) {
- atStart = true;
- } else if (readLine.startsWith("Content-Type")) {
- rawMimeType = readLine.split(": ")[1];
- }
- }
-
- contentLength -= (boundary.length() + CRLF.length() + 2
- * DASHDASH.length() + 2); // 2 == CRLF
-
- /*
- * Reads bytes from the underlying stream. Compares the read bytes to
- * the boundary string and returns -1 if met.
- *
- * The matching happens so that if the read byte equals to the first
- * char of boundary string, the stream goes to "buffering mode". In
- * buffering mode bytes are read until the character does not match the
- * corresponding from boundary string or the full boundary string is
- * found.
- *
- * Note, if this is someday needed elsewhere, don't shoot yourself to
- * foot and split to a top level helper class.
- */
- InputStream simpleMultiPartReader = new SimpleMultiPartInputStream(
- inputStream, boundary);
-
- /*
- * Should report only the filename even if the browser sends the path
- */
- final String filename = removePath(rawfilename);
- final String mimeType = rawMimeType;
-
- try {
- // TODO Shouldn't this check connectorEnabled?
- if (owner == null) {
- throw new UploadException(
- "File upload ignored because the connector for the stream variable was not found");
- }
- if (owner instanceof Component) {
- if (((Component) owner).isReadOnly()) {
- throw new UploadException(
- "Warning: file upload ignored because the componente was read-only");
- }
- }
- boolean forgetVariable = streamToReceiver(simpleMultiPartReader,
- streamVariable, filename, mimeType, contentLength);
- if (forgetVariable) {
- cleanStreamVariable(owner, variableName);
- }
- } catch (Exception e) {
- synchronized (application) {
- handleChangeVariablesError(application, (Component) owner, e,
- new HashMap<String, Object>());
- }
- }
- sendUploadResponse(request, response);
-
- }
-
- /**
- * Used to stream plain file post (aka XHR2.post(File))
- *
- * @param request
- * @param response
- * @param streamVariable
- * @param owner
- * @param contentLength
- * @throws IOException
- */
- protected void doHandleXhrFilePost(WrappedRequest request,
- WrappedResponse response, StreamVariable streamVariable,
- String variableName, ClientConnector owner, int contentLength)
- throws IOException {
-
- // These are unknown in filexhr ATM, maybe add to Accept header that
- // is accessible in portlets
- final String filename = "unknown";
- final String mimeType = filename;
- final InputStream stream = request.getInputStream();
- try {
- /*
- * safe cast as in GWT terminal all variable owners are expected to
- * be components.
- */
- Component component = (Component) owner;
- if (component.isReadOnly()) {
- throw new UploadException(
- "Warning: file upload ignored because the component was read-only");
- }
- boolean forgetVariable = streamToReceiver(stream, streamVariable,
- filename, mimeType, contentLength);
- if (forgetVariable) {
- cleanStreamVariable(owner, variableName);
- }
- } catch (Exception e) {
- synchronized (application) {
- handleChangeVariablesError(application, (Component) owner, e,
- new HashMap<String, Object>());
- }
- }
- sendUploadResponse(request, response);
- }
-
- /**
- * @param in
- * @param streamVariable
- * @param filename
- * @param type
- * @param contentLength
- * @return true if the streamvariable has informed that the terminal can
- * forget this variable
- * @throws UploadException
- */
- protected final boolean streamToReceiver(final InputStream in,
- StreamVariable streamVariable, String filename, String type,
- int contentLength) throws UploadException {
- if (streamVariable == null) {
- throw new IllegalStateException(
- "StreamVariable for the post not found");
- }
-
- final Application application = getApplication();
-
- OutputStream out = null;
- int totalBytes = 0;
- StreamingStartEventImpl startedEvent = new StreamingStartEventImpl(
- filename, type, contentLength);
- try {
- boolean listenProgress;
- synchronized (application) {
- streamVariable.streamingStarted(startedEvent);
- out = streamVariable.getOutputStream();
- listenProgress = streamVariable.listenProgress();
- }
-
- // Gets the output target stream
- if (out == null) {
- throw new NoOutputStreamException();
- }
-
- if (null == in) {
- // No file, for instance non-existent filename in html upload
- throw new NoInputStreamException();
- }
-
- final byte buffer[] = new byte[MAX_UPLOAD_BUFFER_SIZE];
- int bytesReadToBuffer = 0;
- while ((bytesReadToBuffer = in.read(buffer)) > 0) {
- out.write(buffer, 0, bytesReadToBuffer);
- totalBytes += bytesReadToBuffer;
- if (listenProgress) {
- // update progress if listener set and contentLength
- // received
- synchronized (application) {
- StreamingProgressEventImpl progressEvent = new StreamingProgressEventImpl(
- filename, type, contentLength, totalBytes);
- streamVariable.onProgress(progressEvent);
- }
- }
- if (streamVariable.isInterrupted()) {
- throw new UploadInterruptedException();
- }
- }
-
- // upload successful
- out.close();
- StreamingEndEvent event = new StreamingEndEventImpl(filename, type,
- totalBytes);
- synchronized (application) {
- streamVariable.streamingFinished(event);
- }
-
- } catch (UploadInterruptedException e) {
- // Download interrupted by application code
- tryToCloseStream(out);
- StreamingErrorEvent event = new StreamingErrorEventImpl(filename,
- type, contentLength, totalBytes, e);
- synchronized (application) {
- streamVariable.streamingFailed(event);
- }
- // Note, we are not throwing interrupted exception forward as it is
- // not a terminal level error like all other exception.
- } catch (final Exception e) {
- tryToCloseStream(out);
- synchronized (application) {
- StreamingErrorEvent event = new StreamingErrorEventImpl(
- filename, type, contentLength, totalBytes, e);
- synchronized (application) {
- streamVariable.streamingFailed(event);
- }
- // throw exception for terminal to be handled (to be passed to
- // terminalErrorHandler)
- throw new UploadException(e);
- }
- }
- return startedEvent.isDisposed();
- }
-
- static void tryToCloseStream(OutputStream out) {
- try {
- // try to close output stream (e.g. file handle)
- if (out != null) {
- out.close();
- }
- } catch (IOException e1) {
- // NOP
- }
- }
-
- /**
- * Removes any possible path information from the filename and returns the
- * filename. Separators / and \\ are used.
- *
- * @param name
- * @return
- */
- private static String removePath(String filename) {
- if (filename != null) {
- filename = filename.replaceAll("^.*[/\\\\]", "");
- }
-
- return filename;
- }
-
- /**
- * TODO document
- *
- * @param request
- * @param response
- * @throws IOException
- */
- protected void sendUploadResponse(WrappedRequest request,
- WrappedResponse response) throws IOException {
- response.setContentType("text/html");
- final OutputStream out = response.getOutputStream();
- final PrintWriter outWriter = new PrintWriter(new BufferedWriter(
- new OutputStreamWriter(out, "UTF-8")));
- outWriter.print("<html><body>download handled</body></html>");
- outWriter.flush();
- out.close();
- }
-
- /**
- * Internally process a UIDL request from the client.
- *
- * This method calls
- * {@link #handleVariables(WrappedRequest, WrappedResponse, Callback, Application, Root)}
- * to process any changes to variables by the client and then repaints
- * affected components using {@link #paintAfterVariableChanges()}.
- *
- * Also, some cleanup is done when a request arrives for an application that
- * has already been closed.
- *
- * The method handleUidlRequest(...) in subclasses should call this method.
- *
- * TODO better documentation
- *
- * @param request
- * @param response
- * @param callback
- * @param root
- * target window for the UIDL request, can be null if target not
- * found
- * @throws IOException
- * @throws InvalidUIDLSecurityKeyException
- * @throws JSONException
- */
- public void handleUidlRequest(WrappedRequest request,
- WrappedResponse response, Callback callback, Root root)
- throws IOException, InvalidUIDLSecurityKeyException, JSONException {
-
- checkWidgetsetVersion(request);
- requestThemeName = request.getParameter("theme");
- maxInactiveInterval = request.getSessionMaxInactiveInterval();
- // repaint requested or session has timed out and new one is created
- boolean repaintAll;
- final OutputStream out;
-
- repaintAll = (request.getParameter(GET_PARAM_REPAINT_ALL) != null);
- // || (request.getSession().isNew()); FIXME What the h*ll is this??
- out = response.getOutputStream();
-
- boolean analyzeLayouts = false;
- if (repaintAll) {
- // analyzing can be done only with repaintAll
- analyzeLayouts = (request.getParameter(GET_PARAM_ANALYZE_LAYOUTS) != null);
-
- if (request.getParameter(GET_PARAM_HIGHLIGHT_COMPONENT) != null) {
- String pid = request
- .getParameter(GET_PARAM_HIGHLIGHT_COMPONENT);
- highlightedConnector = root.getConnectorTracker().getConnector(
- pid);
- highlightConnector(highlightedConnector);
- }
- }
-
- final PrintWriter outWriter = new PrintWriter(new BufferedWriter(
- new OutputStreamWriter(out, "UTF-8")));
-
- // The rest of the process is synchronized with the application
- // in order to guarantee that no parallel variable handling is
- // made
- synchronized (application) {
-
- // Finds the window within the application
- if (application.isRunning()) {
- // Returns if no window found
- if (root == null) {
- // This should not happen, no windows exists but
- // application is still open.
- getLogger().warning("Could not get root for application");
- return;
- }
- } else {
- // application has been closed
- endApplication(request, response, application);
- return;
- }
-
- // Change all variables based on request parameters
- if (!handleVariables(request, response, callback, application, root)) {
-
- // var inconsistency; the client is probably out-of-sync
- SystemMessages ci = null;
- try {
- Method m = application.getClass().getMethod(
- "getSystemMessages", (Class[]) null);
- ci = (Application.SystemMessages) m.invoke(null,
- (Object[]) null);
- } catch (Exception e2) {
- // FIXME: Handle exception
- // Not critical, but something is still wrong; print
- // stacktrace
- getLogger().log(Level.WARNING,
- "getSystemMessages() failed - continuing", e2);
- }
- if (ci != null) {
- String msg = ci.getOutOfSyncMessage();
- String cap = ci.getOutOfSyncCaption();
- if (msg != null || cap != null) {
- callback.criticalNotification(request, response, cap,
- msg, null, ci.getOutOfSyncURL());
- // will reload page after this
- return;
- }
- }
- // No message to show, let's just repaint all.
- repaintAll = true;
- }
-
- paintAfterVariableChanges(request, response, callback, repaintAll,
- outWriter, root, analyzeLayouts);
- postPaint(root);
- }
-
- outWriter.close();
- requestThemeName = null;
- }
-
- /**
- * Checks that the version reported by the client (widgetset) matches that
- * of the server.
- *
- * @param request
- */
- private void checkWidgetsetVersion(WrappedRequest request) {
- String widgetsetVersion = request.getParameter("wsver");
- if (widgetsetVersion == null) {
- // Only check when the widgetset version is reported. It is reported
- // in the first UIDL request (not the initial request as it is a
- // plain GET /)
- return;
- }
-
- if (!Version.getFullVersion().equals(widgetsetVersion)) {
- getLogger().warning(
- String.format(Constants.WIDGETSET_MISMATCH_INFO,
- Version.getFullVersion(), widgetsetVersion));
- }
- }
-
- /**
- * Method called after the paint phase while still being synchronized on the
- * application
- *
- * @param root
- *
- */
- protected void postPaint(Root root) {
- // Remove connectors that have been detached from the application during
- // handling of the request
- root.getConnectorTracker().cleanConnectorMap();
-
- if (pidToNameToStreamVariable != null) {
- Iterator<String> iterator = pidToNameToStreamVariable.keySet()
- .iterator();
- while (iterator.hasNext()) {
- String connectorId = iterator.next();
- if (root.getConnectorTracker().getConnector(connectorId) == null) {
- // Owner is no longer attached to the application
- Map<String, StreamVariable> removed = pidToNameToStreamVariable
- .get(connectorId);
- for (String key : removed.keySet()) {
- streamVariableToSeckey.remove(removed.get(key));
- }
- iterator.remove();
- }
- }
- }
- }
-
- protected void highlightConnector(Connector highlightedConnector) {
- StringBuilder sb = new StringBuilder();
- sb.append("*** Debug details of a component: *** \n");
- sb.append("Type: ");
- sb.append(highlightedConnector.getClass().getName());
- if (highlightedConnector instanceof AbstractComponent) {
- AbstractComponent component = (AbstractComponent) highlightedConnector;
- sb.append("\nId:");
- sb.append(highlightedConnector.getConnectorId());
- if (component.getCaption() != null) {
- sb.append("\nCaption:");
- sb.append(component.getCaption());
- }
-
- printHighlightedComponentHierarchy(sb, component);
- }
- getLogger().info(sb.toString());
- }
-
- protected void printHighlightedComponentHierarchy(StringBuilder sb,
- AbstractComponent component) {
- LinkedList<Component> h = new LinkedList<Component>();
- h.add(component);
- Component parent = component.getParent();
- while (parent != null) {
- h.addFirst(parent);
- parent = parent.getParent();
- }
-
- sb.append("\nComponent hierarchy:\n");
- Application application2 = component.getApplication();
- sb.append(application2.getClass().getName());
- sb.append(".");
- sb.append(application2.getClass().getSimpleName());
- sb.append("(");
- sb.append(application2.getClass().getSimpleName());
- sb.append(".java");
- sb.append(":1)");
- int l = 1;
- for (Component component2 : h) {
- sb.append("\n");
- for (int i = 0; i < l; i++) {
- sb.append(" ");
- }
- l++;
- Class<? extends Component> componentClass = component2.getClass();
- Class<?> topClass = componentClass;
- while (topClass.getEnclosingClass() != null) {
- topClass = topClass.getEnclosingClass();
- }
- sb.append(componentClass.getName());
- sb.append(".");
- sb.append(componentClass.getSimpleName());
- sb.append("(");
- sb.append(topClass.getSimpleName());
- sb.append(".java:1)");
- }
- }
-
- /**
- * TODO document
- *
- * @param request
- * @param response
- * @param callback
- * @param repaintAll
- * @param outWriter
- * @param window
- * @param analyzeLayouts
- * @throws PaintException
- * @throws IOException
- * @throws JSONException
- */
- private void paintAfterVariableChanges(WrappedRequest request,
- WrappedResponse response, Callback callback, boolean repaintAll,
- final PrintWriter outWriter, Root root, boolean analyzeLayouts)
- throws PaintException, IOException, JSONException {
-
- // Removes application if it has stopped during variable changes
- if (!application.isRunning()) {
- endApplication(request, response, application);
- return;
- }
-
- openJsonMessage(outWriter, response);
-
- // security key
- Object writeSecurityTokenFlag = request
- .getAttribute(WRITE_SECURITY_TOKEN_FLAG);
-
- if (writeSecurityTokenFlag != null) {
- outWriter.print(getSecurityKeyUIDL(request));
- }
-
- writeUidlResponse(request, repaintAll, outWriter, root, analyzeLayouts);
-
- closeJsonMessage(outWriter);
-
- outWriter.close();
-
- }
-
- /**
- * Gets the security key (and generates one if needed) as UIDL.
- *
- * @param request
- * @return the security key UIDL or "" if the feature is turned off
- */
- public String getSecurityKeyUIDL(WrappedRequest request) {
- final String seckey = getSecurityKey(request);
- if (seckey != null) {
- return "\"" + ApplicationConnection.UIDL_SECURITY_TOKEN_ID
- + "\":\"" + seckey + "\",";
- } else {
- return "";
- }
- }
-
- /**
- * Gets the security key (and generates one if needed).
- *
- * @param request
- * @return the security key
- */
- protected String getSecurityKey(WrappedRequest request) {
- String seckey = null;
- seckey = (String) request
- .getSessionAttribute(ApplicationConnection.UIDL_SECURITY_TOKEN_ID);
- if (seckey == null) {
- seckey = UUID.randomUUID().toString();
- request.setSessionAttribute(
- ApplicationConnection.UIDL_SECURITY_TOKEN_ID, seckey);
- }
-
- return seckey;
- }
-
- @SuppressWarnings("unchecked")
- public void writeUidlResponse(WrappedRequest request, boolean repaintAll,
- final PrintWriter outWriter, Root root, boolean analyzeLayouts)
- throws PaintException, JSONException {
- ArrayList<ClientConnector> dirtyVisibleConnectors = new ArrayList<ClientConnector>();
- Application application = root.getApplication();
- // Paints components
- ConnectorTracker rootConnectorTracker = root.getConnectorTracker();
- getLogger().log(Level.FINE, "* Creating response to client");
- if (repaintAll) {
- getClientCache(root).clear();
- rootConnectorTracker.markAllConnectorsDirty();
-
- // Reset sent locales
- locales = null;
- requireLocale(application.getLocale().toString());
- }
-
- dirtyVisibleConnectors
- .addAll(getDirtyVisibleConnectors(rootConnectorTracker));
-
- getLogger().log(
- Level.FINE,
- "Found " + dirtyVisibleConnectors.size()
- + " dirty connectors to paint");
- for (ClientConnector connector : dirtyVisibleConnectors) {
- if (connector instanceof Component) {
- ((Component) connector).updateState();
- }
- }
- rootConnectorTracker.markAllConnectorsClean();
-
- outWriter.print("\"changes\":[");
-
- List<InvalidLayout> invalidComponentRelativeSizes = null;
-
- JsonPaintTarget paintTarget = new JsonPaintTarget(this, outWriter,
- !repaintAll);
- legacyPaint(paintTarget, dirtyVisibleConnectors);
-
- if (analyzeLayouts) {
- invalidComponentRelativeSizes = ComponentSizeValidator
- .validateComponentRelativeSizes(root.getContent(), null,
- null);
-
- // Also check any existing subwindows
- if (root.getWindows() != null) {
- for (Window subWindow : root.getWindows()) {
- invalidComponentRelativeSizes = ComponentSizeValidator
- .validateComponentRelativeSizes(
- subWindow.getContent(),
- invalidComponentRelativeSizes, null);
- }
- }
- }
-
- paintTarget.close();
- outWriter.print("], "); // close changes
-
- // send shared state to client
-
- // for now, send the complete state of all modified and new
- // components
-
- // Ideally, all this would be sent before "changes", but that causes
- // complications with legacy components that create sub-components
- // in their paint phase. Nevertheless, this will be processed on the
- // client after component creation but before legacy UIDL
- // processing.
- JSONObject sharedStates = new JSONObject();
- for (ClientConnector connector : dirtyVisibleConnectors) {
- SharedState state = connector.getState();
- if (null != state) {
- // encode and send shared state
- try {
- Class<? extends SharedState> stateType = connector
- .getStateType();
- SharedState referenceState = null;
- if (repaintAll) {
- // Use an empty state object as reference for full
- // repaints
- try {
- referenceState = stateType.newInstance();
- } catch (Exception e) {
- getLogger().log(
- Level.WARNING,
- "Error creating reference object for state of type "
- + stateType.getName());
- }
- }
- Object stateJson = JsonCodec.encode(state, referenceState,
- stateType, root.getConnectorTracker());
-
- sharedStates.put(connector.getConnectorId(), stateJson);
- } catch (JSONException e) {
- throw new PaintException(
- "Failed to serialize shared state for connector "
- + connector.getClass().getName() + " ("
- + connector.getConnectorId() + "): "
- + e.getMessage(), e);
- }
- }
- }
- outWriter.print("\"state\":");
- outWriter.append(sharedStates.toString());
- outWriter.print(", "); // close states
-
- // TODO This should be optimized. The type only needs to be
- // sent once for each connector id + on refresh. Use the same cache as
- // widget mapping
-
- JSONObject connectorTypes = new JSONObject();
- for (ClientConnector connector : dirtyVisibleConnectors) {
- String connectorType = paintTarget.getTag(connector);
- try {
- connectorTypes.put(connector.getConnectorId(), connectorType);
- } catch (JSONException e) {
- throw new PaintException(
- "Failed to send connector type for connector "
- + connector.getConnectorId() + ": "
- + e.getMessage(), e);
- }
- }
- outWriter.print("\"types\":");
- outWriter.append(connectorTypes.toString());
- outWriter.print(", "); // close states
-
- // Send update hierarchy information to the client.
-
- // This could be optimized aswell to send only info if hierarchy has
- // actually changed. Much like with the shared state. Note though
- // that an empty hierarchy is information aswell (e.g. change from 1
- // child to 0 children)
-
- outWriter.print("\"hierarchy\":");
-
- JSONObject hierarchyInfo = new JSONObject();
- for (ClientConnector connector : dirtyVisibleConnectors) {
- String connectorId = connector.getConnectorId();
- JSONArray children = new JSONArray();
-
- for (ClientConnector child : AbstractClientConnector
- .getAllChildrenIterable(connector)) {
- if (isVisible(child)) {
- children.put(child.getConnectorId());
- }
- }
- try {
- hierarchyInfo.put(connectorId, children);
- } catch (JSONException e) {
- throw new PaintException(
- "Failed to send hierarchy information about "
- + connectorId + " to the client: "
- + e.getMessage(), e);
- }
- }
- outWriter.append(hierarchyInfo.toString());
- outWriter.print(", "); // close hierarchy
-
- // send server to client RPC calls for components in the root, in call
- // order
-
- // collect RPC calls from components in the root in the order in
- // which they were performed, remove the calls from components
-
- LinkedList<ClientConnector> rpcPendingQueue = new LinkedList<ClientConnector>(
- dirtyVisibleConnectors);
- List<ClientMethodInvocation> pendingInvocations = collectPendingRpcCalls(dirtyVisibleConnectors);
-
- JSONArray rpcCalls = new JSONArray();
- for (ClientMethodInvocation invocation : pendingInvocations) {
- // add invocation to rpcCalls
- try {
- JSONArray invocationJson = new JSONArray();
- invocationJson.put(invocation.getConnector().getConnectorId());
- invocationJson.put(invocation.getInterfaceName());
- invocationJson.put(invocation.getMethodName());
- JSONArray paramJson = new JSONArray();
- for (int i = 0; i < invocation.getParameterTypes().length; ++i) {
- Type parameterType = invocation.getParameterTypes()[i];
- Object referenceParameter = null;
- // TODO Use default values for RPC parameter types
- // if (!JsonCodec.isInternalType(parameterType)) {
- // try {
- // referenceParameter = parameterType.newInstance();
- // } catch (Exception e) {
- // logger.log(Level.WARNING,
- // "Error creating reference object for parameter of type "
- // + parameterType.getName());
- // }
- // }
- paramJson.put(JsonCodec.encode(
- invocation.getParameters()[i], referenceParameter,
- parameterType, root.getConnectorTracker()));
- }
- invocationJson.put(paramJson);
- rpcCalls.put(invocationJson);
- } catch (JSONException e) {
- throw new PaintException(
- "Failed to serialize RPC method call parameters for connector "
- + invocation.getConnector().getConnectorId()
- + " method " + invocation.getInterfaceName()
- + "." + invocation.getMethodName() + ": "
- + e.getMessage(), e);
- }
-
- }
-
- if (rpcCalls.length() > 0) {
- outWriter.print("\"rpc\" : ");
- outWriter.append(rpcCalls.toString());
- outWriter.print(", "); // close rpc
- }
-
- outWriter.print("\"meta\" : {");
- boolean metaOpen = false;
-
- if (repaintAll) {
- metaOpen = true;
- outWriter.write("\"repaintAll\":true");
- if (analyzeLayouts) {
- outWriter.write(", \"invalidLayouts\":");
- outWriter.write("[");
- if (invalidComponentRelativeSizes != null) {
- boolean first = true;
- for (InvalidLayout invalidLayout : invalidComponentRelativeSizes) {
- if (!first) {
- outWriter.write(",");
- } else {
- first = false;
- }
- invalidLayout.reportErrors(outWriter, this, System.err);
- }
- }
- outWriter.write("]");
- }
- if (highlightedConnector != null) {
- outWriter.write(", \"hl\":\"");
- outWriter.write(highlightedConnector.getConnectorId());
- outWriter.write("\"");
- highlightedConnector = null;
- }
- }
-
- SystemMessages ci = null;
- try {
- Method m = application.getClass().getMethod("getSystemMessages",
- (Class[]) null);
- ci = (Application.SystemMessages) m.invoke(null, (Object[]) null);
- } catch (NoSuchMethodException e) {
- getLogger().log(Level.WARNING,
- "getSystemMessages() failed - continuing", e);
- } catch (IllegalArgumentException e) {
- getLogger().log(Level.WARNING,
- "getSystemMessages() failed - continuing", e);
- } catch (IllegalAccessException e) {
- getLogger().log(Level.WARNING,
- "getSystemMessages() failed - continuing", e);
- } catch (InvocationTargetException e) {
- getLogger().log(Level.WARNING,
- "getSystemMessages() failed - continuing", e);
- }
-
- // meta instruction for client to enable auto-forward to
- // sessionExpiredURL after timer expires.
- if (ci != null && ci.getSessionExpiredMessage() == null
- && ci.getSessionExpiredCaption() == null
- && ci.isSessionExpiredNotificationEnabled()) {
- int newTimeoutInterval = getTimeoutInterval();
- if (repaintAll || (timeoutInterval != newTimeoutInterval)) {
- String escapedURL = ci.getSessionExpiredURL() == null ? "" : ci
- .getSessionExpiredURL().replace("/", "\\/");
- if (metaOpen) {
- outWriter.write(",");
- }
- outWriter.write("\"timedRedirect\":{\"interval\":"
- + (newTimeoutInterval + 15) + ",\"url\":\""
- + escapedURL + "\"}");
- metaOpen = true;
- }
- timeoutInterval = newTimeoutInterval;
- }
-
- outWriter.print("}, \"resources\" : {");
-
- // Precache custom layouts
-
- // TODO We should only precache the layouts that are not
- // cached already (plagiate from usedPaintableTypes)
- int resourceIndex = 0;
- for (final Iterator<Object> i = paintTarget.getUsedResources()
- .iterator(); i.hasNext();) {
- final String resource = (String) i.next();
- InputStream is = null;
- try {
- is = getThemeResourceAsStream(root, getTheme(root), resource);
- } catch (final Exception e) {
- // FIXME: Handle exception
- getLogger().log(Level.FINER,
- "Failed to get theme resource stream.", e);
- }
- if (is != null) {
-
- outWriter.print((resourceIndex++ > 0 ? ", " : "") + "\""
- + resource + "\" : ");
- final StringBuffer layout = new StringBuffer();
-
- try {
- final InputStreamReader r = new InputStreamReader(is,
- "UTF-8");
- final char[] buffer = new char[20000];
- int charsRead = 0;
- while ((charsRead = r.read(buffer)) > 0) {
- layout.append(buffer, 0, charsRead);
- }
- r.close();
- } catch (final java.io.IOException e) {
- // FIXME: Handle exception
- getLogger().log(Level.INFO, "Resource transfer failed", e);
- }
- outWriter.print("\""
- + JsonPaintTarget.escapeJSON(layout.toString()) + "\"");
- } else {
- // FIXME: Handle exception
- getLogger().severe("CustomLayout not found: " + resource);
- }
- }
- outWriter.print("}");
-
- Collection<Class<? extends ClientConnector>> usedClientConnectors = paintTarget
- .getUsedClientConnectors();
- boolean typeMappingsOpen = false;
- ClientCache clientCache = getClientCache(root);
-
- List<Class<? extends ClientConnector>> newConnectorTypes = new ArrayList<Class<? extends ClientConnector>>();
-
- for (Class<? extends ClientConnector> class1 : usedClientConnectors) {
- if (clientCache.cache(class1)) {
- // client does not know the mapping key for this type, send
- // mapping to client
- newConnectorTypes.add(class1);
-
- if (!typeMappingsOpen) {
- typeMappingsOpen = true;
- outWriter.print(", \"typeMappings\" : { ");
- } else {
- outWriter.print(" , ");
- }
- String canonicalName = class1.getCanonicalName();
- outWriter.print("\"");
- outWriter.print(canonicalName);
- outWriter.print("\" : ");
- outWriter.print(getTagForType(class1));
- }
- }
- if (typeMappingsOpen) {
- outWriter.print(" }");
- }
-
- boolean typeInheritanceMapOpen = false;
- if (typeMappingsOpen) {
- // send the whole type inheritance map if any new mappings
- for (Class<? extends ClientConnector> class1 : usedClientConnectors) {
- if (!ClientConnector.class.isAssignableFrom(class1
- .getSuperclass())) {
- continue;
- }
- if (!typeInheritanceMapOpen) {
- typeInheritanceMapOpen = true;
- outWriter.print(", \"typeInheritanceMap\" : { ");
- } else {
- outWriter.print(" , ");
- }
- outWriter.print("\"");
- outWriter.print(getTagForType(class1));
- outWriter.print("\" : ");
- outWriter
- .print(getTagForType((Class<? extends ClientConnector>) class1
- .getSuperclass()));
- }
- if (typeInheritanceMapOpen) {
- outWriter.print(" }");
- }
- }
-
- /*
- * Ensure super classes come before sub classes to get script dependency
- * order right. Sub class @JavaScript might assume that @JavaScript
- * defined by super class is already loaded.
- */
- Collections.sort(newConnectorTypes, new Comparator<Class<?>>() {
- @Override
- public int compare(Class<?> o1, Class<?> o2) {
- // TODO optimize using Class.isAssignableFrom?
- return hierarchyDepth(o1) - hierarchyDepth(o2);
- }
-
- private int hierarchyDepth(Class<?> type) {
- if (type == Object.class) {
- return 0;
- } else {
- return hierarchyDepth(type.getSuperclass()) + 1;
- }
- }
- });
-
- List<String> scriptDependencies = new ArrayList<String>();
- List<String> styleDependencies = new ArrayList<String>();
-
- for (Class<? extends ClientConnector> class1 : newConnectorTypes) {
- JavaScript jsAnnotation = class1.getAnnotation(JavaScript.class);
- if (jsAnnotation != null) {
- for (String resource : jsAnnotation.value()) {
- scriptDependencies.add(registerResource(resource, class1));
- }
- }
-
- StyleSheet styleAnnotation = class1.getAnnotation(StyleSheet.class);
- if (styleAnnotation != null) {
- for (String resource : styleAnnotation.value()) {
- styleDependencies.add(registerResource(resource, class1));
- }
- }
- }
-
- // Include script dependencies in output if there are any
- if (!scriptDependencies.isEmpty()) {
- outWriter.print(", \"scriptDependencies\": "
- + new JSONArray(scriptDependencies).toString());
- }
-
- // Include style dependencies in output if there are any
- if (!styleDependencies.isEmpty()) {
- outWriter.print(", \"styleDependencies\": "
- + new JSONArray(styleDependencies).toString());
- }
-
- // add any pending locale definitions requested by the client
- printLocaleDeclarations(outWriter);
-
- if (dragAndDropService != null) {
- dragAndDropService.printJSONResponse(outWriter);
- }
-
- writePerformanceData(outWriter);
- }
-
- /**
- * Resolves a resource URI, registering the URI with this
- * {@code AbstractCommunicationManager} if needed and returns a fully
- * qualified URI.
- */
- private String registerResource(String resourceUri, Class<?> context) {
- try {
- URI uri = new URI(resourceUri);
- String protocol = uri.getScheme();
-
- if ("connector".equals(protocol)) {
- // Strip initial slash
- String resourceName = uri.getPath().substring(1);
- return registerConnectorResource(resourceName, context);
- }
-
- if (protocol != null || uri.getHost() != null) {
- return resourceUri;
- }
-
- // Bare path interpreted as connector resource
- return registerConnectorResource(resourceUri, context);
- } catch (URISyntaxException e) {
- getLogger().log(Level.WARNING,
- "Could not parse resource url " + resourceUri, e);
- return resourceUri;
- }
- }
-
- private String registerConnectorResource(String name, Class<?> context) {
- synchronized (connectorResourceContexts) {
- // Add to map of names accepted by serveConnectorResource
- if (connectorResourceContexts.containsKey(name)) {
- Class<?> oldContext = connectorResourceContexts.get(name);
- if (oldContext != context) {
- getLogger().warning(
- "Resource " + name + " defined by both " + context
- + " and " + oldContext + ". Resource from "
- + oldContext + " will be used.");
- }
- } else {
- connectorResourceContexts.put(name, context);
- }
- }
-
- return ApplicationConnection.CONNECTOR_PROTOCOL_PREFIX + "/" + name;
- }
-
- /**
- * Adds the performance timing data (used by TestBench 3) to the UIDL
- * response.
- */
- private void writePerformanceData(final PrintWriter outWriter) {
- AbstractWebApplicationContext ctx = (AbstractWebApplicationContext) application
- .getContext();
- outWriter.write(String.format(", \"timings\":[%d, %d]",
- ctx.getTotalSessionTime(), ctx.getLastRequestTime()));
- }
-
- private void legacyPaint(PaintTarget paintTarget,
- ArrayList<ClientConnector> dirtyVisibleConnectors)
- throws PaintException {
- List<Vaadin6Component> legacyComponents = new ArrayList<Vaadin6Component>();
- for (Connector connector : dirtyVisibleConnectors) {
- // All Components that want to use paintContent must implement
- // Vaadin6Component
- if (connector instanceof Vaadin6Component) {
- legacyComponents.add((Vaadin6Component) connector);
- }
- }
- sortByHierarchy((List) legacyComponents);
- for (Vaadin6Component c : legacyComponents) {
- getLogger().fine(
- "Painting Vaadin6Component " + c.getClass().getName() + "@"
- + Integer.toHexString(c.hashCode()));
- paintTarget.startTag("change");
- final String pid = c.getConnectorId();
- paintTarget.addAttribute("pid", pid);
- LegacyPaint.paint(c, paintTarget);
- paintTarget.endTag("change");
- }
-
- }
-
- private void sortByHierarchy(List<Component> paintables) {
- // Vaadin 6 requires parents to be painted before children as component
- // containers rely on that their updateFromUIDL method has been called
- // before children start calling e.g. updateCaption
- Collections.sort(paintables, new Comparator<Component>() {
-
- @Override
- public int compare(Component c1, Component c2) {
- int depth1 = 0;
- while (c1.getParent() != null) {
- depth1++;
- c1 = c1.getParent();
- }
- int depth2 = 0;
- while (c2.getParent() != null) {
- depth2++;
- c2 = c2.getParent();
- }
- if (depth1 < depth2) {
- return -1;
- }
- if (depth1 > depth2) {
- return 1;
- }
- return 0;
- }
- });
-
- }
-
- private ClientCache getClientCache(Root root) {
- Integer rootId = Integer.valueOf(root.getRootId());
- ClientCache cache = rootToClientCache.get(rootId);
- if (cache == null) {
- cache = new ClientCache();
- rootToClientCache.put(rootId, cache);
- }
- return cache;
- }
-
- /**
- * Checks if the connector is visible in context. For Components,
- * {@link #isVisible(Component)} is used. For other types of connectors, the
- * contextual visibility of its first Component ancestor is used. If no
- * Component ancestor is found, the connector is not visible.
- *
- * @param connector
- * The connector to check
- * @return <code>true</code> if the connector is visible to the client,
- * <code>false</code> otherwise
- */
- static boolean isVisible(ClientConnector connector) {
- if (connector instanceof Component) {
- return isVisible((Component) connector);
- } else {
- ClientConnector parent = connector.getParent();
- if (parent == null) {
- return false;
- } else {
- return isVisible(parent);
- }
- }
- }
-
- /**
- * Checks if the component is visible in context, i.e. returns false if the
- * child is hidden, the parent is hidden or the parent says the child should
- * not be rendered (using
- * {@link HasComponents#isComponentVisible(Component)}
- *
- * @param child
- * The child to check
- * @return true if the child is visible to the client, false otherwise
- */
- static boolean isVisible(Component child) {
- if (!child.isVisible()) {
- return false;
- }
-
- HasComponents parent = child.getParent();
- if (parent == null) {
- if (child instanceof Root) {
- return child.isVisible();
- } else {
- return false;
- }
- }
-
- return parent.isComponentVisible(child) && isVisible(parent);
- }
-
- private static class NullIterator<E> implements Iterator<E> {
-
- @Override
- public boolean hasNext() {
- return false;
- }
-
- @Override
- public E next() {
- return null;
- }
-
- @Override
- public void remove() {
- }
-
- }
-
- /**
- * Collects all pending RPC calls from listed {@link ClientConnector}s and
- * clears their RPC queues.
- *
- * @param rpcPendingQueue
- * list of {@link ClientConnector} of interest
- * @return ordered list of pending RPC calls
- */
- private List<ClientMethodInvocation> collectPendingRpcCalls(
- List<ClientConnector> rpcPendingQueue) {
- List<ClientMethodInvocation> pendingInvocations = new ArrayList<ClientMethodInvocation>();
- for (ClientConnector connector : rpcPendingQueue) {
- List<ClientMethodInvocation> paintablePendingRpc = connector
- .retrievePendingRpcCalls();
- if (null != paintablePendingRpc && !paintablePendingRpc.isEmpty()) {
- List<ClientMethodInvocation> oldPendingRpc = pendingInvocations;
- int totalCalls = pendingInvocations.size()
- + paintablePendingRpc.size();
- pendingInvocations = new ArrayList<ClientMethodInvocation>(
- totalCalls);
-
- // merge two ordered comparable lists
- for (int destIndex = 0, oldIndex = 0, paintableIndex = 0; destIndex < totalCalls; destIndex++) {
- if (paintableIndex >= paintablePendingRpc.size()
- || (oldIndex < oldPendingRpc.size() && ((Comparable<ClientMethodInvocation>) oldPendingRpc
- .get(oldIndex))
- .compareTo(paintablePendingRpc
- .get(paintableIndex)) <= 0)) {
- pendingInvocations.add(oldPendingRpc.get(oldIndex++));
- } else {
- pendingInvocations.add(paintablePendingRpc
- .get(paintableIndex++));
- }
- }
- }
- }
- return pendingInvocations;
- }
-
- protected abstract InputStream getThemeResourceAsStream(Root root,
- String themeName, String resource);
-
- private int getTimeoutInterval() {
- return maxInactiveInterval;
- }
-
- private String getTheme(Root root) {
- String themeName = root.getApplication().getThemeForRoot(root);
- String requestThemeName = getRequestTheme();
-
- if (requestThemeName != null) {
- themeName = requestThemeName;
- }
- if (themeName == null) {
- themeName = AbstractApplicationServlet.getDefaultTheme();
- }
- return themeName;
- }
-
- private String getRequestTheme() {
- return requestThemeName;
- }
-
- /**
- * Returns false if the cross site request forgery protection is turned off.
- *
- * @param application
- * @return false if the XSRF is turned off, true otherwise
- */
- public boolean isXSRFEnabled(Application application) {
- return !"true"
- .equals(application
- .getProperty(AbstractApplicationServlet.SERVLET_PARAMETER_DISABLE_XSRF_PROTECTION));
- }
-
- /**
- * TODO document
- *
- * If this method returns false, something was submitted that we did not
- * expect; this is probably due to the client being out-of-sync and sending
- * variable changes for non-existing pids
- *
- * @return true if successful, false if there was an inconsistency
- */
- private boolean handleVariables(WrappedRequest request,
- WrappedResponse response, Callback callback,
- Application application2, Root root) throws IOException,
- InvalidUIDLSecurityKeyException, JSONException {
- boolean success = true;
-
- String changes = getRequestPayload(request);
- if (changes != null) {
-
- // Manage bursts one by one
- final String[] bursts = changes.split(String
- .valueOf(VAR_BURST_SEPARATOR));
-
- // Security: double cookie submission pattern unless disabled by
- // property
- if (isXSRFEnabled(application2)) {
- if (bursts.length == 1 && "init".equals(bursts[0])) {
- // init request; don't handle any variables, key sent in
- // response.
- request.setAttribute(WRITE_SECURITY_TOKEN_FLAG, true);
- return true;
- } else {
- // ApplicationServlet has stored the security token in the
- // session; check that it matched the one sent in the UIDL
- String sessId = (String) request
- .getSessionAttribute(ApplicationConnection.UIDL_SECURITY_TOKEN_ID);
-
- if (sessId == null || !sessId.equals(bursts[0])) {
- throw new InvalidUIDLSecurityKeyException(
- "Security key mismatch");
- }
- }
-
- }
-
- for (int bi = 1; bi < bursts.length; bi++) {
- // unescape any encoded separator characters in the burst
- final String burst = unescapeBurst(bursts[bi]);
- success &= handleBurst(request, root, burst);
-
- // In case that there were multiple bursts, we know that this is
- // a special synchronous case for closing window. Thus we are
- // not interested in sending any UIDL changes back to client.
- // Still we must clear component tree between bursts to ensure
- // that no removed components are updated. The painting after
- // the last burst is handled normally by the calling method.
- if (bi < bursts.length - 1) {
-
- // We will be discarding all changes
- final PrintWriter outWriter = new PrintWriter(
- new CharArrayWriter());
-
- paintAfterVariableChanges(request, response, callback,
- true, outWriter, root, false);
-
- }
-
- }
- }
- /*
- * Note that we ignore inconsistencies while handling unload request.
- * The client can't remove invalid variable changes from the burst, and
- * we don't have the required logic implemented on the server side. E.g.
- * a component is removed in a previous burst.
- */
- return success;
- }
-
- /**
- * Processes a message burst received from the client.
- *
- * A burst can contain any number of RPC calls, including legacy variable
- * change calls that are processed separately.
- *
- * Consecutive changes to the value of the same variable are combined and
- * changeVariables() is only called once for them. This preserves the Vaadin
- * 6 semantics for components and add-ons that do not use Vaadin 7 RPC
- * directly.
- *
- * @param source
- * @param root
- * the root receiving the burst
- * @param burst
- * the content of the burst as a String to be parsed
- * @return true if the processing of the burst was successful and there were
- * no messages to non-existent components
- */
- public boolean handleBurst(WrappedRequest source, Root root,
- final String burst) {
- boolean success = true;
- try {
- Set<Connector> enabledConnectors = new HashSet<Connector>();
-
- List<MethodInvocation> invocations = parseInvocations(
- root.getConnectorTracker(), burst);
- for (MethodInvocation invocation : invocations) {
- final ClientConnector connector = getConnector(root,
- invocation.getConnectorId());
-
- if (connector != null && connector.isConnectorEnabled()) {
- enabledConnectors.add(connector);
- }
- }
-
- for (int i = 0; i < invocations.size(); i++) {
- MethodInvocation invocation = invocations.get(i);
-
- final ClientConnector connector = getConnector(root,
- invocation.getConnectorId());
-
- if (connector == null) {
- getLogger().log(
- Level.WARNING,
- "RPC call to " + invocation.getInterfaceName()
- + "." + invocation.getMethodName()
- + " received for connector "
- + invocation.getConnectorId()
- + " but no such connector could be found");
- continue;
- }
-
- if (!enabledConnectors.contains(connector)) {
-
- if (invocation instanceof LegacyChangeVariablesInvocation) {
- LegacyChangeVariablesInvocation legacyInvocation = (LegacyChangeVariablesInvocation) invocation;
- // TODO convert window close to a separate RPC call and
- // handle above - not a variable change
-
- // Handle special case where window-close is called
- // after the window has been removed from the
- // application or the application has closed
- Map<String, Object> changes = legacyInvocation
- .getVariableChanges();
- if (changes.size() == 1 && changes.containsKey("close")
- && Boolean.TRUE.equals(changes.get("close"))) {
- // Silently ignore this
- continue;
- }
- }
-
- // Connector is disabled, log a warning and move to the next
- String msg = "Ignoring RPC call for disabled connector "
- + connector.getClass().getName();
- if (connector instanceof Component) {
- String caption = ((Component) connector).getCaption();
- if (caption != null) {
- msg += ", caption=" + caption;
- }
- }
- getLogger().warning(msg);
- continue;
- }
-
- if (invocation instanceof ServerRpcMethodInvocation) {
- try {
- ServerRpcManager.applyInvocation(connector,
- (ServerRpcMethodInvocation) invocation);
- } catch (RpcInvocationException e) {
- Throwable realException = e.getCause();
- Component errorComponent = null;
- if (connector instanceof Component) {
- errorComponent = (Component) connector;
- }
- handleChangeVariablesError(root.getApplication(),
- errorComponent, realException, null);
- }
- } else {
-
- // All code below is for legacy variable changes
- LegacyChangeVariablesInvocation legacyInvocation = (LegacyChangeVariablesInvocation) invocation;
- Map<String, Object> changes = legacyInvocation
- .getVariableChanges();
- try {
- if (connector instanceof VariableOwner) {
- changeVariables(source, (VariableOwner) connector,
- changes);
- } else {
- throw new IllegalStateException(
- "Received legacy variable change for "
- + connector.getClass().getName()
- + " ("
- + connector.getConnectorId()
- + ") which is not a VariableOwner. The client-side connector sent these legacy varaibles: "
- + changes.keySet());
- }
- } catch (Exception e) {
- Component errorComponent = null;
- if (connector instanceof Component) {
- errorComponent = (Component) connector;
- } else if (connector instanceof DragAndDropService) {
- Object dropHandlerOwner = changes.get("dhowner");
- if (dropHandlerOwner instanceof Component) {
- errorComponent = (Component) dropHandlerOwner;
- }
- }
- handleChangeVariablesError(root.getApplication(),
- errorComponent, e, changes);
- }
- }
- }
- } catch (JSONException e) {
- getLogger().warning(
- "Unable to parse RPC call from the client: "
- + e.getMessage());
- // TODO or return success = false?
- throw new RuntimeException(e);
- }
-
- return success;
- }
-
- /**
- * Parse a message burst from the client into a list of MethodInvocation
- * instances.
- *
- * @param connectorTracker
- * The ConnectorTracker used to lookup connectors
- * @param burst
- * message string (JSON)
- * @return list of MethodInvocation to perform
- * @throws JSONException
- */
- private List<MethodInvocation> parseInvocations(
- ConnectorTracker connectorTracker, final String burst)
- throws JSONException {
- JSONArray invocationsJson = new JSONArray(burst);
-
- ArrayList<MethodInvocation> invocations = new ArrayList<MethodInvocation>();
-
- MethodInvocation previousInvocation = null;
- // parse JSON to MethodInvocations
- for (int i = 0; i < invocationsJson.length(); ++i) {
-
- JSONArray invocationJson = invocationsJson.getJSONArray(i);
-
- MethodInvocation invocation = parseInvocation(invocationJson,
- previousInvocation, connectorTracker);
- if (invocation != null) {
- // Can be null iff the invocation was a legacy invocation and it
- // was merged with the previous one
- invocations.add(invocation);
- previousInvocation = invocation;
- }
- }
- return invocations;
- }
-
- private MethodInvocation parseInvocation(JSONArray invocationJson,
- MethodInvocation previousInvocation,
- ConnectorTracker connectorTracker) throws JSONException {
- String connectorId = invocationJson.getString(0);
- String interfaceName = invocationJson.getString(1);
- String methodName = invocationJson.getString(2);
-
- JSONArray parametersJson = invocationJson.getJSONArray(3);
-
- if (LegacyChangeVariablesInvocation.isLegacyVariableChange(
- interfaceName, methodName)) {
- if (!(previousInvocation instanceof LegacyChangeVariablesInvocation)) {
- previousInvocation = null;
- }
-
- return parseLegacyChangeVariablesInvocation(connectorId,
- interfaceName, methodName,
- (LegacyChangeVariablesInvocation) previousInvocation,
- parametersJson, connectorTracker);
- } else {
- return parseServerRpcInvocation(connectorId, interfaceName,
- methodName, parametersJson, connectorTracker);
- }
-
- }
-
- private LegacyChangeVariablesInvocation parseLegacyChangeVariablesInvocation(
- String connectorId, String interfaceName, String methodName,
- LegacyChangeVariablesInvocation previousInvocation,
- JSONArray parametersJson, ConnectorTracker connectorTracker)
- throws JSONException {
- if (parametersJson.length() != 2) {
- throw new JSONException(
- "Invalid parameters in legacy change variables call. Expected 2, was "
- + parametersJson.length());
- }
- String variableName = parametersJson.getString(0);
- UidlValue uidlValue = (UidlValue) JsonCodec.decodeInternalType(
- UidlValue.class, true, parametersJson.get(1), connectorTracker);
-
- Object value = uidlValue.getValue();
-
- if (previousInvocation != null
- && previousInvocation.getConnectorId().equals(connectorId)) {
- previousInvocation.setVariableChange(variableName, value);
- return null;
- } else {
- return new LegacyChangeVariablesInvocation(connectorId,
- variableName, value);
- }
- }
-
- private ServerRpcMethodInvocation parseServerRpcInvocation(
- String connectorId, String interfaceName, String methodName,
- JSONArray parametersJson, ConnectorTracker connectorTracker)
- throws JSONException {
- ServerRpcMethodInvocation invocation = new ServerRpcMethodInvocation(
- connectorId, interfaceName, methodName, parametersJson.length());
-
- Object[] parameters = new Object[parametersJson.length()];
- Type[] declaredRpcMethodParameterTypes = invocation.getMethod()
- .getGenericParameterTypes();
-
- for (int j = 0; j < parametersJson.length(); ++j) {
- Object parameterValue = parametersJson.get(j);
- Type parameterType = declaredRpcMethodParameterTypes[j];
- parameters[j] = JsonCodec.decodeInternalOrCustomType(parameterType,
- parameterValue, connectorTracker);
- }
- invocation.setParameters(parameters);
- return invocation;
- }
-
- protected void changeVariables(Object source, final VariableOwner owner,
- Map<String, Object> m) {
- owner.changeVariables(source, m);
- }
-
- protected ClientConnector getConnector(Root root, String connectorId) {
- ClientConnector c = root.getConnectorTracker()
- .getConnector(connectorId);
- if (c == null
- && connectorId.equals(getDragAndDropService().getConnectorId())) {
- return getDragAndDropService();
- }
-
- return c;
- }
-
- private DragAndDropService getDragAndDropService() {
- if (dragAndDropService == null) {
- dragAndDropService = new DragAndDropService(this);
- }
- return dragAndDropService;
- }
-
- /**
- * Reads the request data from the Request and returns it converted to an
- * UTF-8 string.
- *
- * @param request
- * @return
- * @throws IOException
- */
- protected String getRequestPayload(WrappedRequest request)
- throws IOException {
-
- int requestLength = request.getContentLength();
- if (requestLength == 0) {
- return null;
- }
-
- ByteArrayOutputStream bout = requestLength <= 0 ? new ByteArrayOutputStream()
- : new ByteArrayOutputStream(requestLength);
-
- InputStream inputStream = request.getInputStream();
- byte[] buffer = new byte[MAX_BUFFER_SIZE];
-
- while (true) {
- int read = inputStream.read(buffer);
- if (read == -1) {
- break;
- }
- bout.write(buffer, 0, read);
- }
- String result = new String(bout.toByteArray(), "utf-8");
-
- return result;
- }
-
- public class ErrorHandlerErrorEvent implements ErrorEvent, Serializable {
- private final Throwable throwable;
-
- public ErrorHandlerErrorEvent(Throwable throwable) {
- this.throwable = throwable;
- }
-
- @Override
- public Throwable getThrowable() {
- return throwable;
- }
-
- }
-
- /**
- * Handles an error (exception) that occurred when processing variable
- * changes from the client or a failure of a file upload.
- *
- * For {@link AbstractField} components,
- * {@link AbstractField#handleError(com.vaadin.ui.AbstractComponent.ComponentErrorEvent)}
- * is called. In all other cases (or if the field does not handle the
- * error), {@link ErrorListener#terminalError(ErrorEvent)} for the
- * application error handler is called.
- *
- * @param application
- * @param owner
- * component that the error concerns
- * @param e
- * exception that occurred
- * @param m
- * map from variable names to values
- */
- private void handleChangeVariablesError(Application application,
- Component owner, Throwable t, Map<String, Object> m) {
- boolean handled = false;
- ChangeVariablesErrorEvent errorEvent = new ChangeVariablesErrorEvent(
- owner, t, m);
-
- if (owner instanceof AbstractField) {
- try {
- handled = ((AbstractField<?>) owner).handleError(errorEvent);
- } catch (Exception handlerException) {
- /*
- * If there is an error in the component error handler we pass
- * the that error to the application error handler and continue
- * processing the actual error
- */
- application.getErrorHandler().terminalError(
- new ErrorHandlerErrorEvent(handlerException));
- handled = false;
- }
- }
-
- if (!handled) {
- application.getErrorHandler().terminalError(errorEvent);
- }
-
- }
-
- /**
- * Unescape encoded burst separator characters in a burst received from the
- * client. This protects from separator injection attacks.
- *
- * @param encodedValue
- * to decode
- * @return decoded value
- */
- protected String unescapeBurst(String encodedValue) {
- final StringBuilder result = new StringBuilder();
- final StringCharacterIterator iterator = new StringCharacterIterator(
- encodedValue);
- char character = iterator.current();
- while (character != CharacterIterator.DONE) {
- if (VAR_ESCAPE_CHARACTER == character) {
- character = iterator.next();
- switch (character) {
- case VAR_ESCAPE_CHARACTER + 0x30:
- // escaped escape character
- result.append(VAR_ESCAPE_CHARACTER);
- break;
- case VAR_BURST_SEPARATOR + 0x30:
- // +0x30 makes these letters for easier reading
- result.append((char) (character - 0x30));
- break;
- case CharacterIterator.DONE:
- // error
- throw new RuntimeException(
- "Communication error: Unexpected end of message");
- default:
- // other escaped character - probably a client-server
- // version mismatch
- throw new RuntimeException(
- "Invalid escaped character from the client - check that the widgetset and server versions match");
- }
- } else {
- // not a special character - add it to the result as is
- result.append(character);
- }
- character = iterator.next();
- }
- return result.toString();
- }
-
- /**
- * Prints the queued (pending) locale definitions to a {@link PrintWriter}
- * in a (UIDL) format that can be sent to the client and used there in
- * formatting dates, times etc.
- *
- * @param outWriter
- */
- private void printLocaleDeclarations(PrintWriter outWriter) {
- /*
- * ----------------------------- Sending Locale sensitive date
- * -----------------------------
- */
-
- // Send locale informations to client
- outWriter.print(", \"locales\":[");
- for (; pendingLocalesIndex < locales.size(); pendingLocalesIndex++) {
-
- final Locale l = generateLocale(locales.get(pendingLocalesIndex));
- // Locale name
- outWriter.print("{\"name\":\"" + l.toString() + "\",");
-
- /*
- * Month names (both short and full)
- */
- final DateFormatSymbols dfs = new DateFormatSymbols(l);
- final String[] short_months = dfs.getShortMonths();
- final String[] months = dfs.getMonths();
- outWriter.print("\"smn\":[\""
- + // ShortMonthNames
- short_months[0] + "\",\"" + short_months[1] + "\",\""
- + short_months[2] + "\",\"" + short_months[3] + "\",\""
- + short_months[4] + "\",\"" + short_months[5] + "\",\""
- + short_months[6] + "\",\"" + short_months[7] + "\",\""
- + short_months[8] + "\",\"" + short_months[9] + "\",\""
- + short_months[10] + "\",\"" + short_months[11] + "\""
- + "],");
- outWriter.print("\"mn\":[\""
- + // MonthNames
- months[0] + "\",\"" + months[1] + "\",\"" + months[2]
- + "\",\"" + months[3] + "\",\"" + months[4] + "\",\""
- + months[5] + "\",\"" + months[6] + "\",\"" + months[7]
- + "\",\"" + months[8] + "\",\"" + months[9] + "\",\""
- + months[10] + "\",\"" + months[11] + "\"" + "],");
-
- /*
- * Weekday names (both short and full)
- */
- final String[] short_days = dfs.getShortWeekdays();
- final String[] days = dfs.getWeekdays();
- outWriter.print("\"sdn\":[\""
- + // ShortDayNames
- short_days[1] + "\",\"" + short_days[2] + "\",\""
- + short_days[3] + "\",\"" + short_days[4] + "\",\""
- + short_days[5] + "\",\"" + short_days[6] + "\",\""
- + short_days[7] + "\"" + "],");
- outWriter.print("\"dn\":[\""
- + // DayNames
- days[1] + "\",\"" + days[2] + "\",\"" + days[3] + "\",\""
- + days[4] + "\",\"" + days[5] + "\",\"" + days[6] + "\",\""
- + days[7] + "\"" + "],");
-
- /*
- * First day of week (0 = sunday, 1 = monday)
- */
- final Calendar cal = new GregorianCalendar(l);
- outWriter.print("\"fdow\":" + (cal.getFirstDayOfWeek() - 1) + ",");
-
- /*
- * Date formatting (MM/DD/YYYY etc.)
- */
-
- DateFormat dateFormat = DateFormat.getDateTimeInstance(
- DateFormat.SHORT, DateFormat.SHORT, l);
- if (!(dateFormat instanceof SimpleDateFormat)) {
- getLogger().warning(
- "Unable to get default date pattern for locale "
- + l.toString());
- dateFormat = new SimpleDateFormat();
- }
- final String df = ((SimpleDateFormat) dateFormat).toPattern();
-
- int timeStart = df.indexOf("H");
- if (timeStart < 0) {
- timeStart = df.indexOf("h");
- }
- final int ampm_first = df.indexOf("a");
- // E.g. in Korean locale AM/PM is before h:mm
- // TODO should take that into consideration on client-side as well,
- // now always h:mm a
- if (ampm_first > 0 && ampm_first < timeStart) {
- timeStart = ampm_first;
- }
- // Hebrew locale has time before the date
- final boolean timeFirst = timeStart == 0;
- String dateformat;
- if (timeFirst) {
- int dateStart = df.indexOf(' ');
- if (ampm_first > dateStart) {
- dateStart = df.indexOf(' ', ampm_first);
- }
- dateformat = df.substring(dateStart + 1);
- } else {
- dateformat = df.substring(0, timeStart - 1);
- }
-
- outWriter.print("\"df\":\"" + dateformat.trim() + "\",");
-
- /*
- * Time formatting (24 or 12 hour clock and AM/PM suffixes)
- */
- final String timeformat = df.substring(timeStart, df.length());
- /*
- * Doesn't return second or milliseconds.
- *
- * We use timeformat to determine 12/24-hour clock
- */
- final boolean twelve_hour_clock = timeformat.indexOf("a") > -1;
- // TODO there are other possibilities as well, like 'h' in french
- // (ignore them, too complicated)
- final String hour_min_delimiter = timeformat.indexOf(".") > -1 ? "."
- : ":";
- // outWriter.print("\"tf\":\"" + timeformat + "\",");
- outWriter.print("\"thc\":" + twelve_hour_clock + ",");
- outWriter.print("\"hmd\":\"" + hour_min_delimiter + "\"");
- if (twelve_hour_clock) {
- final String[] ampm = dfs.getAmPmStrings();
- outWriter.print(",\"ampm\":[\"" + ampm[0] + "\",\"" + ampm[1]
- + "\"]");
- }
- outWriter.print("}");
- if (pendingLocalesIndex < locales.size() - 1) {
- outWriter.print(",");
- }
- }
- outWriter.print("]"); // Close locales
- }
-
- /**
- * Ends the Application.
- *
- * The browser is redirected to the Application logout URL set with
- * {@link Application#setLogoutURL(String)}, or to the application URL if no
- * logout URL is given.
- *
- * @param request
- * the request instance.
- * @param response
- * the response to write to.
- * @param application
- * the Application to end.
- * @throws IOException
- * if the writing failed due to input/output error.
- */
- private void endApplication(WrappedRequest request,
- WrappedResponse response, Application application)
- throws IOException {
-
- String logoutUrl = application.getLogoutURL();
- if (logoutUrl == null) {
- logoutUrl = application.getURL().toString();
- }
- // clients JS app is still running, send a special json file to tell
- // client that application has quit and where to point browser now
- // Set the response type
- final OutputStream out = response.getOutputStream();
- final PrintWriter outWriter = new PrintWriter(new BufferedWriter(
- new OutputStreamWriter(out, "UTF-8")));
- openJsonMessage(outWriter, response);
- outWriter.print("\"redirect\":{");
- outWriter.write("\"url\":\"" + logoutUrl + "\"}");
- closeJsonMessage(outWriter);
- outWriter.flush();
- outWriter.close();
- out.flush();
- }
-
- protected void closeJsonMessage(PrintWriter outWriter) {
- outWriter.print("}]");
- }
-
- /**
- * Writes the opening of JSON message to be sent to client.
- *
- * @param outWriter
- * @param response
- */
- protected void openJsonMessage(PrintWriter outWriter,
- WrappedResponse response) {
- // Sets the response type
- response.setContentType("application/json; charset=UTF-8");
- // some dirt to prevent cross site scripting
- outWriter.print("for(;;);[{");
- }
-
- /**
- * Returns dirty components which are in given window. Components in an
- * invisible subtrees are omitted.
- *
- * @param w
- * root window for which dirty components is to be fetched
- * @return
- */
- private ArrayList<ClientConnector> getDirtyVisibleConnectors(
- ConnectorTracker connectorTracker) {
- ArrayList<ClientConnector> dirtyConnectors = new ArrayList<ClientConnector>();
- for (ClientConnector c : connectorTracker.getDirtyConnectors()) {
- if (isVisible(c)) {
- dirtyConnectors.add(c);
- }
- }
-
- return dirtyConnectors;
- }
-
- /**
- * Queues a locale to be sent to the client (browser) for date and time
- * entry etc. All locale specific information is derived from server-side
- * {@link Locale} instances and sent to the client when needed, eliminating
- * the need to use the {@link Locale} class and all the framework behind it
- * on the client.
- *
- * @see Locale#toString()
- *
- * @param value
- */
- public void requireLocale(String value) {
- if (locales == null) {
- locales = new ArrayList<String>();
- locales.add(application.getLocale().toString());
- pendingLocalesIndex = 0;
- }
- if (!locales.contains(value)) {
- locales.add(value);
- }
- }
-
- /**
- * Constructs a {@link Locale} instance to be sent to the client based on a
- * short locale description string.
- *
- * @see #requireLocale(String)
- *
- * @param value
- * @return
- */
- private Locale generateLocale(String value) {
- final String[] temp = value.split("_");
- if (temp.length == 1) {
- return new Locale(temp[0]);
- } else if (temp.length == 2) {
- return new Locale(temp[0], temp[1]);
- } else {
- return new Locale(temp[0], temp[1], temp[2]);
- }
- }
-
- protected class InvalidUIDLSecurityKeyException extends
- GeneralSecurityException {
-
- InvalidUIDLSecurityKeyException(String message) {
- super(message);
- }
-
- }
-
- private final HashMap<Class<? extends ClientConnector>, Integer> typeToKey = new HashMap<Class<? extends ClientConnector>, Integer>();
- private int nextTypeKey = 0;
-
- private BootstrapHandler bootstrapHandler;
-
- String getTagForType(Class<? extends ClientConnector> class1) {
- Integer id = typeToKey.get(class1);
- if (id == null) {
- id = nextTypeKey++;
- typeToKey.put(class1, id);
- getLogger().log(Level.FINE,
- "Mapping " + class1.getName() + " to " + id);
- }
- return id.toString();
- }
-
- /**
- * Helper class for terminal to keep track of data that client is expected
- * to know.
- *
- * TODO make customlayout templates (from theme) to be cached here.
- */
- class ClientCache implements Serializable {
-
- private final Set<Object> res = new HashSet<Object>();
-
- /**
- *
- * @param paintable
- * @return true if the given class was added to cache
- */
- boolean cache(Object object) {
- return res.add(object);
- }
-
- public void clear() {
- res.clear();
- }
-
- }
-
- public String getStreamVariableTargetUrl(ClientConnector owner,
- String name, StreamVariable value) {
- /*
- * We will use the same APP/* URI space as ApplicationResources but
- * prefix url with UPLOAD
- *
- * eg. APP/UPLOAD/[ROOTID]/[PID]/[NAME]/[SECKEY]
- *
- * SECKEY is created on each paint to make URL's unpredictable (to
- * prevent CSRF attacks).
- *
- * NAME and PID from URI forms a key to fetch StreamVariable when
- * handling post
- */
- String paintableId = owner.getConnectorId();
- int rootId = owner.getRoot().getRootId();
- String key = rootId + "/" + paintableId + "/" + name;
-
- if (pidToNameToStreamVariable == null) {
- pidToNameToStreamVariable = new HashMap<String, Map<String, StreamVariable>>();
- }
- Map<String, StreamVariable> nameToStreamVariable = pidToNameToStreamVariable
- .get(paintableId);
- if (nameToStreamVariable == null) {
- nameToStreamVariable = new HashMap<String, StreamVariable>();
- pidToNameToStreamVariable.put(paintableId, nameToStreamVariable);
- }
- nameToStreamVariable.put(name, value);
-
- if (streamVariableToSeckey == null) {
- streamVariableToSeckey = new HashMap<StreamVariable, String>();
- }
- String seckey = streamVariableToSeckey.get(value);
- if (seckey == null) {
- seckey = UUID.randomUUID().toString();
- streamVariableToSeckey.put(value, seckey);
- }
-
- return ApplicationConnection.APP_PROTOCOL_PREFIX
- + ServletPortletHelper.UPLOAD_URL_PREFIX + key + "/" + seckey;
-
- }
-
- public void cleanStreamVariable(ClientConnector owner, String name) {
- Map<String, StreamVariable> nameToStreamVar = pidToNameToStreamVariable
- .get(owner.getConnectorId());
- nameToStreamVar.remove(name);
- if (nameToStreamVar.isEmpty()) {
- pidToNameToStreamVariable.remove(owner.getConnectorId());
- }
- }
-
- /**
- * Gets the bootstrap handler that should be used for generating the pages
- * bootstrapping applications for this communication manager.
- *
- * @return the bootstrap handler to use
- */
- private BootstrapHandler getBootstrapHandler() {
- if (bootstrapHandler == null) {
- bootstrapHandler = createBootstrapHandler();
- }
-
- return bootstrapHandler;
- }
-
- protected abstract BootstrapHandler createBootstrapHandler();
-
- protected boolean handleApplicationRequest(WrappedRequest request,
- WrappedResponse response) throws IOException {
- return application.handleRequest(request, response);
- }
-
- public void handleBrowserDetailsRequest(WrappedRequest request,
- WrappedResponse response, Application application)
- throws IOException {
-
- // if we do not yet have a currentRoot, it should be initialized
- // shortly, and we should send the initial UIDL
- boolean sendUIDL = Root.getCurrent() == null;
-
- try {
- CombinedRequest combinedRequest = new CombinedRequest(request);
-
- Root root = application.getRootForRequest(combinedRequest);
- response.setContentType("application/json; charset=UTF-8");
-
- // Use the same logic as for determined roots
- BootstrapHandler bootstrapHandler = getBootstrapHandler();
- BootstrapContext context = bootstrapHandler.createContext(
- combinedRequest, response, application, root.getRootId(),
- null);
-
- String widgetset = context.getWidgetsetName();
- String theme = context.getThemeName();
- String themeUri = bootstrapHandler.getThemeUri(context, theme);
-
- // TODO These are not required if it was only the init of the root
- // that was delayed
- JSONObject params = new JSONObject();
- params.put("widgetset", widgetset);
- params.put("themeUri", themeUri);
- // Root id might have changed based on e.g. window.name
- params.put(ApplicationConnection.ROOT_ID_PARAMETER,
- root.getRootId());
- if (sendUIDL) {
- String initialUIDL = getInitialUIDL(combinedRequest, root);
- params.put("uidl", initialUIDL);
- }
-
- // NOTE! GateIn requires, for some weird reason, getOutputStream
- // to be used instead of getWriter() (it seems to interpret
- // application/json as a binary content type)
- final OutputStream out = response.getOutputStream();
- final PrintWriter outWriter = new PrintWriter(new BufferedWriter(
- new OutputStreamWriter(out, "UTF-8")));
-
- outWriter.write(params.toString());
- // NOTE GateIn requires the buffers to be flushed to work
- outWriter.flush();
- out.flush();
- } catch (RootRequiresMoreInformationException e) {
- // Requiring more information at this point is not allowed
- // TODO handle in a better way
- throw new RuntimeException(e);
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
-
- /**
- * Generates the initial UIDL message that can e.g. be included in a html
- * page to avoid a separate round trip just for getting the UIDL.
- *
- * @param request
- * the request that caused the initialization
- * @param root
- * the root for which the UIDL should be generated
- * @return a string with the initial UIDL message
- * @throws PaintException
- * if an exception occurs while painting
- * @throws JSONException
- * if an exception occurs while encoding output
- */
- protected String getInitialUIDL(WrappedRequest request, Root root)
- throws PaintException, JSONException {
- // TODO maybe unify writeUidlResponse()?
- StringWriter sWriter = new StringWriter();
- PrintWriter pWriter = new PrintWriter(sWriter);
- pWriter.print("{");
- if (isXSRFEnabled(root.getApplication())) {
- pWriter.print(getSecurityKeyUIDL(request));
- }
- writeUidlResponse(request, true, pWriter, root, false);
- pWriter.print("}");
- String initialUIDL = sWriter.toString();
- getLogger().log(Level.FINE, "Initial UIDL:" + initialUIDL);
- return initialUIDL;
- }
-
- /**
- * Serve a connector resource from the classpath if the resource has
- * previously been registered by calling
- * {@link #registerResource(String, Class)}. Sending arbitrary files from
- * the classpath is prevented by only accepting resource names that have
- * explicitly been registered. Resources can currently only be registered by
- * including a {@link JavaScript} or {@link StyleSheet} annotation on a
- * Connector class.
- *
- * @param request
- * @param response
- *
- * @throws IOException
- */
- public void serveConnectorResource(WrappedRequest request,
- WrappedResponse response) throws IOException {
-
- String pathInfo = request.getRequestPathInfo();
- // + 2 to also remove beginning and ending slashes
- String resourceName = pathInfo
- .substring(ApplicationConnection.CONNECTOR_RESOURCE_PREFIX
- .length() + 2);
-
- final String mimetype = response.getDeploymentConfiguration()
- .getMimeType(resourceName);
-
- // Security check: avoid accidentally serving from the root of the
- // classpath instead of relative to the context class
- if (resourceName.startsWith("/")) {
- getLogger().warning(
- "Connector resource request starting with / rejected: "
- + resourceName);
- response.sendError(HttpServletResponse.SC_NOT_FOUND, resourceName);
- return;
- }
-
- // Check that the resource name has been registered
- Class<?> context;
- synchronized (connectorResourceContexts) {
- context = connectorResourceContexts.get(resourceName);
- }
-
- // Security check: don't serve resource if the name hasn't been
- // registered in the map
- if (context == null) {
- getLogger().warning(
- "Connector resource request for unknown resource rejected: "
- + resourceName);
- response.sendError(HttpServletResponse.SC_NOT_FOUND, resourceName);
- return;
- }
-
- // Resolve file relative to the location of the context class
- InputStream in = context.getResourceAsStream(resourceName);
- if (in == null) {
- getLogger().warning(
- resourceName + " defined by " + context.getName()
- + " not found. Verify that the file "
- + context.getPackage().getName().replace('.', '/')
- + '/' + resourceName
- + " is available on the classpath.");
- response.sendError(HttpServletResponse.SC_NOT_FOUND, resourceName);
- return;
- }
-
- // TODO Check and set cache headers
-
- OutputStream out = null;
- try {
- if (mimetype != null) {
- response.setContentType(mimetype);
- }
-
- out = response.getOutputStream();
-
- final byte[] buffer = new byte[Constants.DEFAULT_BUFFER_SIZE];
-
- int bytesRead = 0;
- while ((bytesRead = in.read(buffer)) > 0) {
- out.write(buffer, 0, bytesRead);
- }
- out.flush();
- } finally {
- try {
- in.close();
- } catch (Exception e) {
- // Do nothing
- }
- if (out != null) {
- try {
- out.close();
- } catch (Exception e) {
- // Do nothing
- }
- }
- }
- }
-
- /**
- * Handles file upload request submitted via Upload component.
- *
- * @param root
- * The root for this request
- *
- * @see #getStreamVariableTargetUrl(ReceiverOwner, String, StreamVariable)
- *
- * @param request
- * @param response
- * @throws IOException
- * @throws InvalidUIDLSecurityKeyException
- */
- public void handleFileUpload(Application application,
- WrappedRequest request, WrappedResponse response)
- throws IOException, InvalidUIDLSecurityKeyException {
-
- /*
- * URI pattern: APP/UPLOAD/[ROOTID]/[PID]/[NAME]/[SECKEY] See
- * #createReceiverUrl
- */
-
- String pathInfo = request.getRequestPathInfo();
- // strip away part until the data we are interested starts
- int startOfData = pathInfo
- .indexOf(ServletPortletHelper.UPLOAD_URL_PREFIX)
- + ServletPortletHelper.UPLOAD_URL_PREFIX.length();
- String uppUri = pathInfo.substring(startOfData);
- String[] parts = uppUri.split("/", 4); // 0= rootid, 1 = cid, 2= name, 3
- // = sec key
- String rootId = parts[0];
- String connectorId = parts[1];
- String variableName = parts[2];
- Root root = application.getRootById(Integer.parseInt(rootId));
- Root.setCurrent(root);
-
- StreamVariable streamVariable = getStreamVariable(connectorId,
- variableName);
- String secKey = streamVariableToSeckey.get(streamVariable);
- if (secKey.equals(parts[3])) {
-
- ClientConnector source = getConnector(root, connectorId);
- String contentType = request.getContentType();
- if (contentType.contains("boundary")) {
- // Multipart requests contain boundary string
- doHandleSimpleMultipartFileUpload(request, response,
- streamVariable, variableName, source,
- contentType.split("boundary=")[1]);
- } else {
- // if boundary string does not exist, the posted file is from
- // XHR2.post(File)
- doHandleXhrFilePost(request, response, streamVariable,
- variableName, source, request.getContentLength());
- }
- } else {
- throw new InvalidUIDLSecurityKeyException(
- "Security key in upload post did not match!");
- }
-
- }
-
- public StreamVariable getStreamVariable(String connectorId,
- String variableName) {
- Map<String, StreamVariable> map = pidToNameToStreamVariable
- .get(connectorId);
- if (map == null) {
- return null;
- }
- StreamVariable streamVariable = map.get(variableName);
- return streamVariable;
- }
-
- /**
- * Stream that extracts content from another stream until the boundary
- * string is encountered.
- *
- * Public only for unit tests, should be considered private for all other
- * purposes.
- */
- public static class SimpleMultiPartInputStream extends InputStream {
-
- /**
- * Counter of how many characters have been matched to boundary string
- * from the stream
- */
- int matchedCount = -1;
-
- /**
- * Used as pointer when returning bytes after partly matched boundary
- * string.
- */
- int curBoundaryIndex = 0;
- /**
- * The byte found after a "promising start for boundary"
- */
- private int bufferedByte = -1;
- private boolean atTheEnd = false;
-
- private final char[] boundary;
-
- private final InputStream realInputStream;
-
- public SimpleMultiPartInputStream(InputStream realInputStream,
- String boundaryString) {
- boundary = (CRLF + DASHDASH + boundaryString).toCharArray();
- this.realInputStream = realInputStream;
- }
-
- @Override
- public int read() throws IOException {
- if (atTheEnd) {
- // End boundary reached, nothing more to read
- return -1;
- } else if (bufferedByte >= 0) {
- /* Purge partially matched boundary if there was such */
- return getBuffered();
- } else if (matchedCount != -1) {
- /*
- * Special case where last "failed" matching ended with first
- * character from boundary string
- */
- return matchForBoundary();
- } else {
- int fromActualStream = realInputStream.read();
- if (fromActualStream == -1) {
- // unexpected end of stream
- throw new IOException(
- "The multipart stream ended unexpectedly");
- }
- if (boundary[0] == fromActualStream) {
- /*
- * If matches the first character in boundary string, start
- * checking if the boundary is fetched.
- */
- return matchForBoundary();
- }
- return fromActualStream;
- }
- }
-
- /**
- * Reads the input to expect a boundary string. Expects that the first
- * character has already been matched.
- *
- * @return -1 if the boundary was matched, else returns the first byte
- * from boundary
- * @throws IOException
- */
- private int matchForBoundary() throws IOException {
- matchedCount = 0;
- /*
- * Going to "buffered mode". Read until full boundary match or a
- * different character.
- */
- while (true) {
- matchedCount++;
- if (matchedCount == boundary.length) {
- /*
- * The whole boundary matched so we have reached the end of
- * file
- */
- atTheEnd = true;
- return -1;
- }
- int fromActualStream = realInputStream.read();
- if (fromActualStream != boundary[matchedCount]) {
- /*
- * Did not find full boundary, cache the mismatching byte
- * and start returning the partially matched boundary.
- */
- bufferedByte = fromActualStream;
- return getBuffered();
- }
- }
- }
-
- /**
- * Returns the partly matched boundary string and the byte following
- * that.
- *
- * @return
- * @throws IOException
- */
- private int getBuffered() throws IOException {
- int b;
- if (matchedCount == 0) {
- // The boundary has been returned, return the buffered byte.
- b = bufferedByte;
- bufferedByte = -1;
- matchedCount = -1;
- } else {
- b = boundary[curBoundaryIndex++];
- if (curBoundaryIndex == matchedCount) {
- // The full boundary has been returned, remaining is the
- // char that did not match the boundary.
-
- curBoundaryIndex = 0;
- if (bufferedByte != boundary[0]) {
- /*
- * next call for getBuffered will return the
- * bufferedByte that came after the partial boundary
- * match
- */
- matchedCount = 0;
- } else {
- /*
- * Special case where buffered byte again matches the
- * boundaryString. This could be the start of the real
- * end boundary.
- */
- matchedCount = 0;
- bufferedByte = -1;
- }
- }
- }
- if (b == -1) {
- throw new IOException("The multipart stream ended unexpectedly");
- }
- return b;
- }
- }
-
- private static final Logger getLogger() {
- return Logger.getLogger(AbstractCommunicationManager.class.getName());
- }
-}
diff --git a/src/com/vaadin/terminal/gwt/server/AbstractDeploymentConfiguration.java b/src/com/vaadin/terminal/gwt/server/AbstractDeploymentConfiguration.java
deleted file mode 100644
index 1382c1ed53..0000000000
--- a/src/com/vaadin/terminal/gwt/server/AbstractDeploymentConfiguration.java
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal.gwt.server;
-
-import java.lang.reflect.Constructor;
-import java.util.Iterator;
-import java.util.Properties;
-import java.util.ServiceLoader;
-import java.util.logging.Logger;
-
-import com.vaadin.terminal.DeploymentConfiguration;
-
-public abstract class AbstractDeploymentConfiguration implements
- DeploymentConfiguration {
-
- private final Class<?> systemPropertyBaseClass;
- private final Properties applicationProperties = new Properties();
- private VaadinContext vaadinContext;
- private boolean productionMode;
- private boolean xsrfProtectionEnabled;
- private int resourceCacheTime;
-
- public AbstractDeploymentConfiguration(Class<?> systemPropertyBaseClass) {
- this.systemPropertyBaseClass = systemPropertyBaseClass;
-
- checkProductionMode();
- checkXsrfProtection();
- checkResourceCacheTime();
- }
-
- @Override
- public String getApplicationOrSystemProperty(String propertyName,
- String defaultValue) {
-
- String val = null;
-
- // Try application properties
- val = getApplicationProperty(propertyName);
- if (val != null) {
- return val;
- }
-
- // Try system properties
- val = getSystemProperty(propertyName);
- if (val != null) {
- return val;
- }
-
- return defaultValue;
- }
-
- /**
- * 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 = systemPropertyBaseClass.getPackage();
- if (pkg != null) {
- pkgName = pkg.getName();
- } else {
- final String className = systemPropertyBaseClass.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;
- }
-
- @Override
- public ClassLoader getClassLoader() {
- final String classLoaderName = getApplicationOrSystemProperty(
- "ClassLoader", null);
- ClassLoader classLoader;
- if (classLoaderName == null) {
- classLoader = getClass().getClassLoader();
- } else {
- try {
- final Class<?> classLoaderClass = getClass().getClassLoader()
- .loadClass(classLoaderName);
- final Constructor<?> c = classLoaderClass
- .getConstructor(new Class[] { ClassLoader.class });
- classLoader = (ClassLoader) c
- .newInstance(new Object[] { getClass().getClassLoader() });
- } catch (final Exception e) {
- throw new RuntimeException(
- "Could not find specified class loader: "
- + classLoaderName, e);
- }
- }
- return classLoader;
- }
-
- /**
- * 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;
- }
-
- @Override
- public Properties getInitParameters() {
- return applicationProperties;
- }
-
- @Override
- public Iterator<VaadinContextListener> getContextListeners() {
- // Called once for init and once for destroy, so it's probably not worth
- // the effort caching the ServiceLoader instance
- ServiceLoader<VaadinContextListener> contextListenerLoader = ServiceLoader
- .load(VaadinContextListener.class, getClassLoader());
- return contextListenerLoader.iterator();
- }
-
- @Override
- public void setVaadinContext(VaadinContext vaadinContext) {
- this.vaadinContext = vaadinContext;
- }
-
- @Override
- public VaadinContext getVaadinContext() {
- return vaadinContext;
- }
-
- @Override
- public boolean isProductionMode() {
- return productionMode;
- }
-
- @Override
- public boolean isXsrfProtectionEnabled() {
- return xsrfProtectionEnabled;
- }
-
- @Override
- public int getResourceCacheTime() {
- return resourceCacheTime;
- }
-
- /**
- * Log a warning if Vaadin is not running in production mode.
- */
- private void checkProductionMode() {
- productionMode = getApplicationOrSystemProperty(
- Constants.SERVLET_PARAMETER_PRODUCTION_MODE, "false").equals(
- "true");
- if (!productionMode) {
- getLogger().warning(Constants.NOT_PRODUCTION_MODE_INFO);
- }
- }
-
- /**
- * Log a warning if cross-site request forgery protection is disabled.
- */
- private void checkXsrfProtection() {
- xsrfProtectionEnabled = getApplicationOrSystemProperty(
- Constants.SERVLET_PARAMETER_DISABLE_XSRF_PROTECTION, "false")
- .equals("true");
- if (!xsrfProtectionEnabled) {
- getLogger().warning(Constants.WARNING_XSRF_PROTECTION_DISABLED);
- }
- }
-
- /**
- * Log a warning if resource cache time is set but is not an integer.
- */
- private void checkResourceCacheTime() {
- try {
- resourceCacheTime = Integer
- .parseInt(getApplicationOrSystemProperty(
- Constants.SERVLET_PARAMETER_RESOURCE_CACHE_TIME,
- "3600"));
- } catch (NumberFormatException e) {
- getLogger().warning(
- Constants.WARNING_RESOURCE_CACHING_TIME_NOT_NUMERIC);
- resourceCacheTime = 3600;
- }
- }
-
- private Logger getLogger() {
- return Logger.getLogger(getClass().getName());
- }
-}
diff --git a/src/com/vaadin/terminal/gwt/server/AbstractStreamingEvent.java b/src/com/vaadin/terminal/gwt/server/AbstractStreamingEvent.java
deleted file mode 100644
index d3474e736e..0000000000
--- a/src/com/vaadin/terminal/gwt/server/AbstractStreamingEvent.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.terminal.gwt.server;
-
-import com.vaadin.terminal.StreamVariable.StreamingEvent;
-
-/**
- * Abstract base class for StreamingEvent implementations.
- */
-@SuppressWarnings("serial")
-abstract class AbstractStreamingEvent implements StreamingEvent {
- private final String type;
- private final String filename;
- private final long contentLength;
- private final long bytesReceived;
-
- @Override
- public final String getFileName() {
- return filename;
- }
-
- @Override
- public final String getMimeType() {
- return type;
- }
-
- protected AbstractStreamingEvent(String filename, String type, long length,
- long bytesReceived) {
- this.filename = filename;
- this.type = type;
- contentLength = length;
- this.bytesReceived = bytesReceived;
- }
-
- @Override
- public final long getContentLength() {
- return contentLength;
- }
-
- @Override
- public final long getBytesReceived() {
- return bytesReceived;
- }
-
-}
diff --git a/src/com/vaadin/terminal/gwt/server/AbstractWebApplicationContext.java b/src/com/vaadin/terminal/gwt/server/AbstractWebApplicationContext.java
deleted file mode 100644
index 3a33621d10..0000000000
--- a/src/com/vaadin/terminal/gwt/server/AbstractWebApplicationContext.java
+++ /dev/null
@@ -1,268 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.terminal.gwt.server;
-
-import java.io.PrintWriter;
-import java.io.Serializable;
-import java.io.StringWriter;
-import java.io.UnsupportedEncodingException;
-import java.net.URL;
-import java.net.URLEncoder;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import javax.servlet.http.HttpSessionBindingEvent;
-import javax.servlet.http.HttpSessionBindingListener;
-
-import com.vaadin.Application;
-import com.vaadin.service.ApplicationContext;
-import com.vaadin.terminal.ApplicationResource;
-import com.vaadin.terminal.gwt.client.ApplicationConnection;
-
-/**
- * Base class for web application contexts (including portlet contexts) that
- * handles the common tasks.
- */
-public abstract class AbstractWebApplicationContext implements
- ApplicationContext, HttpSessionBindingListener, Serializable {
-
- protected Collection<TransactionListener> listeners = Collections
- .synchronizedList(new LinkedList<TransactionListener>());
-
- protected final HashSet<Application> applications = new HashSet<Application>();
-
- protected WebBrowser browser = new WebBrowser();
-
- protected HashMap<Application, AbstractCommunicationManager> applicationToAjaxAppMgrMap = new HashMap<Application, AbstractCommunicationManager>();
-
- private long totalSessionTime = 0;
-
- private long lastRequestTime = -1;
-
- @Override
- public void addTransactionListener(TransactionListener listener) {
- if (listener != null) {
- listeners.add(listener);
- }
- }
-
- @Override
- public void removeTransactionListener(TransactionListener listener) {
- listeners.remove(listener);
- }
-
- /**
- * Sends a notification that a transaction is starting.
- *
- * @param application
- * The application associated with the transaction.
- * @param request
- * the HTTP or portlet request that triggered the transaction.
- */
- protected void startTransaction(Application application, Object request) {
- ArrayList<TransactionListener> currentListeners;
- synchronized (listeners) {
- currentListeners = new ArrayList<TransactionListener>(listeners);
- }
- for (TransactionListener listener : currentListeners) {
- listener.transactionStart(application, request);
- }
- }
-
- /**
- * Sends a notification that a transaction has ended.
- *
- * @param application
- * The application associated with the transaction.
- * @param request
- * the HTTP or portlet request that triggered the transaction.
- */
- protected void endTransaction(Application application, Object request) {
- LinkedList<Exception> exceptions = null;
-
- ArrayList<TransactionListener> currentListeners;
- synchronized (listeners) {
- currentListeners = new ArrayList<TransactionListener>(listeners);
- }
-
- for (TransactionListener listener : currentListeners) {
- try {
- listener.transactionEnd(application, request);
- } catch (final RuntimeException t) {
- if (exceptions == null) {
- exceptions = new LinkedList<Exception>();
- }
- exceptions.add(t);
- }
- }
-
- // If any runtime exceptions occurred, throw a combined exception
- if (exceptions != null) {
- final StringBuffer msg = new StringBuffer();
- for (Exception e : exceptions) {
- if (msg.length() == 0) {
- msg.append("\n\n--------------------------\n\n");
- }
- msg.append(e.getMessage() + "\n");
- final StringWriter trace = new StringWriter();
- e.printStackTrace(new PrintWriter(trace, true));
- msg.append(trace.toString());
- }
- throw new RuntimeException(msg.toString());
- }
- }
-
- /**
- * @see javax.servlet.http.HttpSessionBindingListener#valueBound(HttpSessionBindingEvent)
- */
- @Override
- public void valueBound(HttpSessionBindingEvent arg0) {
- // We are not interested in bindings
- }
-
- /**
- * @see javax.servlet.http.HttpSessionBindingListener#valueUnbound(HttpSessionBindingEvent)
- */
- @Override
- public void valueUnbound(HttpSessionBindingEvent event) {
- // If we are going to be unbound from the session, the session must be
- // closing
- try {
- while (!applications.isEmpty()) {
- final Application app = applications.iterator().next();
- app.close();
- removeApplication(app);
- }
- } catch (Exception e) {
- // This should never happen but is possible with rare
- // configurations (e.g. robustness tests). If you have one
- // thread doing HTTP socket write and another thread trying to
- // remove same application here. Possible if you got e.g. session
- // lifetime 1 min but socket write may take longer than 1 min.
- // FIXME: Handle exception
- getLogger().log(Level.SEVERE,
- "Could not remove application, leaking memory.", e);
- }
- }
-
- /**
- * Get the web browser associated with this application context.
- *
- * Because application context is related to the http session and server
- * maintains one session per browser-instance, each context has exactly one
- * web browser associated with it.
- *
- * @return
- */
- public WebBrowser getBrowser() {
- return browser;
- }
-
- @Override
- public Collection<Application> getApplications() {
- return Collections.unmodifiableCollection(applications);
- }
-
- protected void removeApplication(Application application) {
- applications.remove(application);
- applicationToAjaxAppMgrMap.remove(application);
- }
-
- @Override
- public String generateApplicationResourceURL(ApplicationResource resource,
- String mapKey) {
-
- final String filename = resource.getFilename();
- if (filename == null) {
- return ApplicationConnection.APP_PROTOCOL_PREFIX
- + ApplicationConnection.APP_REQUEST_PATH + mapKey + "/";
- } else {
- // #7738 At least Tomcat and JBoss refuses requests containing
- // encoded slashes or backslashes in URLs. Application resource URLs
- // should really be passed in another way than as part of the path
- // in the future.
- String encodedFileName = urlEncode(filename).replace("%2F", "/")
- .replace("%5C", "\\");
- return ApplicationConnection.APP_PROTOCOL_PREFIX
- + ApplicationConnection.APP_REQUEST_PATH + mapKey + "/"
- + encodedFileName;
- }
-
- }
-
- static String urlEncode(String filename) {
- try {
- return URLEncoder.encode(filename, "UTF-8");
- } catch (UnsupportedEncodingException e) {
- throw new RuntimeException(
- "UTF-8 charset not available (\"this should never happen\")",
- e);
- }
- }
-
- @Override
- public boolean isApplicationResourceURL(URL context, String relativeUri) {
- // If the relative uri is null, we are ready
- if (relativeUri == null) {
- return false;
- }
-
- // Resolves the prefix
- String prefix = relativeUri;
- final int index = relativeUri.indexOf('/');
- if (index >= 0) {
- prefix = relativeUri.substring(0, index);
- }
-
- // Handles the resource requests
- return (prefix.equals("APP"));
- }
-
- @Override
- public String getURLKey(URL context, String relativeUri) {
- final int index = relativeUri.indexOf('/');
- final int next = relativeUri.indexOf('/', index + 1);
- if (next < 0) {
- return null;
- }
- return relativeUri.substring(index + 1, next);
- }
-
- /**
- * @return The total time spent servicing requests in this session.
- */
- public long getTotalSessionTime() {
- return totalSessionTime;
- }
-
- /**
- * Sets the time spent servicing the last request in the session and updates
- * the total time spent servicing requests in this session.
- *
- * @param time
- * the time spent in the last request.
- */
- public void setLastRequestTime(long time) {
- lastRequestTime = time;
- totalSessionTime += time;
- }
-
- /**
- * @return the time spent servicing the last request in this session.
- */
- public long getLastRequestTime() {
- return lastRequestTime;
- }
-
- private Logger getLogger() {
- return Logger.getLogger(AbstractWebApplicationContext.class.getName());
- }
-
-} \ No newline at end of file
diff --git a/src/com/vaadin/terminal/gwt/server/ApplicationPortlet2.java b/src/com/vaadin/terminal/gwt/server/ApplicationPortlet2.java
deleted file mode 100644
index 788c48267e..0000000000
--- a/src/com/vaadin/terminal/gwt/server/ApplicationPortlet2.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal.gwt.server;
-
-import javax.portlet.PortletConfig;
-import javax.portlet.PortletException;
-
-import com.vaadin.Application;
-import com.vaadin.terminal.gwt.server.ServletPortletHelper.ApplicationClassException;
-
-/**
- * TODO Write documentation, fix JavaDoc tags.
- *
- * @author peholmst
- */
-public class ApplicationPortlet2 extends AbstractApplicationPortlet {
-
- private Class<? extends Application> applicationClass;
-
- @Override
- public void init(PortletConfig config) throws PortletException {
- super.init(config);
- try {
- applicationClass = ServletPortletHelper
- .getApplicationClass(getDeploymentConfiguration());
- } catch (ApplicationClassException e) {
- throw new PortletException(e);
- }
- }
-
- @Override
- protected Class<? extends Application> getApplicationClass() {
- return applicationClass;
- }
-
-}
diff --git a/src/com/vaadin/terminal/gwt/server/ApplicationResourceHandler.java b/src/com/vaadin/terminal/gwt/server/ApplicationResourceHandler.java
deleted file mode 100644
index 42726c933e..0000000000
--- a/src/com/vaadin/terminal/gwt/server/ApplicationResourceHandler.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal.gwt.server;
-
-import java.io.IOException;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import javax.servlet.http.HttpServletResponse;
-
-import com.vaadin.Application;
-import com.vaadin.terminal.ApplicationResource;
-import com.vaadin.terminal.DownloadStream;
-import com.vaadin.terminal.RequestHandler;
-import com.vaadin.terminal.WrappedRequest;
-import com.vaadin.terminal.WrappedResponse;
-
-public class ApplicationResourceHandler implements RequestHandler {
- private static final Pattern APP_RESOURCE_PATTERN = Pattern
- .compile("^/?APP/(\\d+)/.*");
-
- @Override
- public boolean handleRequest(Application application,
- WrappedRequest request, WrappedResponse response)
- throws IOException {
- // Check for application resources
- String requestPath = request.getRequestPathInfo();
- if (requestPath == null) {
- return false;
- }
- Matcher resourceMatcher = APP_RESOURCE_PATTERN.matcher(requestPath);
-
- if (resourceMatcher.matches()) {
- ApplicationResource resource = application
- .getResource(resourceMatcher.group(1));
- if (resource != null) {
- DownloadStream stream = resource.getStream();
- if (stream != null) {
- stream.setCacheTime(resource.getCacheTime());
- stream.writeTo(response);
- return true;
- }
- }
- // We get here if the url looks like an application resource but no
- // resource can be served
- response.sendError(HttpServletResponse.SC_NOT_FOUND,
- request.getRequestPathInfo() + " can not be found");
- return true;
- }
-
- return false;
- }
-}
diff --git a/src/com/vaadin/terminal/gwt/server/ApplicationServlet.java b/src/com/vaadin/terminal/gwt/server/ApplicationServlet.java
deleted file mode 100644
index 1af49e0da0..0000000000
--- a/src/com/vaadin/terminal/gwt/server/ApplicationServlet.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal.gwt.server;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-
-import com.vaadin.Application;
-import com.vaadin.terminal.gwt.server.ServletPortletHelper.ApplicationClassException;
-
-/**
- * This servlet connects a Vaadin Application to Web.
- *
- * @author Vaadin Ltd.
- * @version
- * @VERSION@
- * @since 5.0
- */
-
-@SuppressWarnings("serial")
-public class ApplicationServlet extends AbstractApplicationServlet {
-
- // Private fields
- private Class<? extends Application> applicationClass;
-
- /**
- * Called by the servlet container to indicate to a servlet that the servlet
- * is being placed into service.
- *
- * @param servletConfig
- * the object containing the servlet's configuration and
- * initialization parameters
- * @throws javax.servlet.ServletException
- * if an exception has occurred that interferes with the
- * servlet's normal operation.
- */
- @Override
- public void init(javax.servlet.ServletConfig servletConfig)
- throws javax.servlet.ServletException {
- super.init(servletConfig);
-
- // Loads the application class using the classloader defined in the
- // deployment configuration
-
- try {
- applicationClass = ServletPortletHelper
- .getApplicationClass(getDeploymentConfiguration());
- } catch (ApplicationClassException e) {
- throw new ServletException(e);
- }
- }
-
- @Override
- protected Application getNewApplication(HttpServletRequest request)
- throws ServletException {
-
- // Creates a new application instance
- try {
- final Application application = getApplicationClass().newInstance();
-
- return application;
- } catch (final IllegalAccessException e) {
- throw new ServletException("getNewApplication failed", e);
- } catch (final InstantiationException e) {
- throw new ServletException("getNewApplication failed", e);
- } catch (ClassNotFoundException e) {
- throw new ServletException("getNewApplication failed", e);
- }
- }
-
- @Override
- protected Class<? extends Application> getApplicationClass()
- throws ClassNotFoundException {
- return applicationClass;
- }
-}
diff --git a/src/com/vaadin/terminal/gwt/server/BootstrapDom.java b/src/com/vaadin/terminal/gwt/server/BootstrapDom.java
deleted file mode 100644
index 4731a5b79f..0000000000
--- a/src/com/vaadin/terminal/gwt/server/BootstrapDom.java
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal.gwt.server;
-
-public class BootstrapDom {
-
-}
diff --git a/src/com/vaadin/terminal/gwt/server/BootstrapHandler.java b/src/com/vaadin/terminal/gwt/server/BootstrapHandler.java
deleted file mode 100644
index d025e93072..0000000000
--- a/src/com/vaadin/terminal/gwt/server/BootstrapHandler.java
+++ /dev/null
@@ -1,643 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal.gwt.server;
-
-import java.io.BufferedWriter;
-import java.io.IOException;
-import java.io.OutputStreamWriter;
-import java.io.Serializable;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-
-import javax.servlet.http.HttpServletResponse;
-
-import org.jsoup.nodes.DataNode;
-import org.jsoup.nodes.Document;
-import org.jsoup.nodes.DocumentType;
-import org.jsoup.nodes.Element;
-import org.jsoup.parser.Tag;
-
-import com.vaadin.Application;
-import com.vaadin.RootRequiresMoreInformationException;
-import com.vaadin.Version;
-import com.vaadin.external.json.JSONException;
-import com.vaadin.external.json.JSONObject;
-import com.vaadin.terminal.DeploymentConfiguration;
-import com.vaadin.terminal.PaintException;
-import com.vaadin.terminal.RequestHandler;
-import com.vaadin.terminal.WrappedRequest;
-import com.vaadin.terminal.WrappedResponse;
-import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.ui.Root;
-
-public abstract class BootstrapHandler implements RequestHandler {
-
- protected class BootstrapContext implements Serializable {
-
- private final WrappedResponse response;
- private final BootstrapResponse bootstrapResponse;
-
- private String widgetsetName;
- private String themeName;
- private String appId;
-
- public BootstrapContext(WrappedResponse response,
- BootstrapResponse bootstrapResponse) {
- this.response = response;
- this.bootstrapResponse = bootstrapResponse;
- }
-
- public WrappedResponse getResponse() {
- return response;
- }
-
- public WrappedRequest getRequest() {
- return bootstrapResponse.getRequest();
- }
-
- public Application getApplication() {
- return bootstrapResponse.getApplication();
- }
-
- public Integer getRootId() {
- return bootstrapResponse.getRootId();
- }
-
- public Root getRoot() {
- return bootstrapResponse.getRoot();
- }
-
- public String getWidgetsetName() {
- if (widgetsetName == null) {
- Root root = getRoot();
- if (root != null) {
- widgetsetName = getWidgetsetForRoot(this);
- }
- }
- return widgetsetName;
- }
-
- public String getThemeName() {
- if (themeName == null) {
- Root root = getRoot();
- if (root != null) {
- themeName = findAndEscapeThemeName(this);
- }
- }
- return themeName;
- }
-
- public String getAppId() {
- if (appId == null) {
- appId = getApplicationId(this);
- }
- return appId;
- }
-
- public BootstrapResponse getBootstrapResponse() {
- return bootstrapResponse;
- }
-
- }
-
- @Override
- public boolean handleRequest(Application application,
- WrappedRequest request, WrappedResponse response)
- throws IOException {
-
- // TODO Should all urls be handled here?
- Integer rootId = null;
- try {
- Root root = application.getRootForRequest(request);
- if (root == null) {
- writeError(response, new Throwable("No Root found"));
- return true;
- }
-
- rootId = Integer.valueOf(root.getRootId());
- } catch (RootRequiresMoreInformationException e) {
- // Just keep going without rootId
- }
-
- try {
- writeBootstrapPage(request, response, application, rootId);
- } catch (JSONException e) {
- writeError(response, e);
- }
-
- return true;
- }
-
- protected final void writeBootstrapPage(WrappedRequest request,
- WrappedResponse response, Application application, Integer rootId)
- throws IOException, JSONException {
-
- Map<String, Object> headers = new LinkedHashMap<String, Object>();
- BootstrapContext context = createContext(request, response,
- application, rootId, headers);
-
- DeploymentConfiguration deploymentConfiguration = request
- .getDeploymentConfiguration();
-
- boolean standalone = deploymentConfiguration.isStandalone(request);
- if (standalone) {
- setBootstrapPageHeaders(context);
- setBasicHtml(context);
- setBootstrapPageHtmlHeader(context);
- setBodyTag(context);
- }
-
- setBootstrapPageHtmlVaadinScripts(context);
-
- setMainDiv(context);
-
- request.getDeploymentConfiguration().getVaadinContext()
- .fireModifyBootstrapEvent(context.getBootstrapResponse());
-
- response.setContentType("text/html");
- BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(
- response.getOutputStream(), "UTF-8"));
- if (standalone) {
- Set<Entry<String, Object>> entrySet = headers.entrySet();
- for (Entry<String, Object> header : entrySet) {
- Object value = header.getValue();
- if (value instanceof String) {
- response.setHeader(header.getKey(), (String) value);
- } else if (value instanceof Long) {
- response.setDateHeader(header.getKey(),
- ((Long) value).longValue());
- } else {
- throw new RuntimeException("Unsupported header value: "
- + value);
- }
- }
- writer.append(context.getBootstrapResponse().getDocument()
- .outerHtml());
- } else {
- writer.append(context.getBootstrapResponse().getApplicationTag()
- .outerHtml());
- }
- writer.close();
- }
-
- public BootstrapContext createContext(WrappedRequest request,
- WrappedResponse response, Application application, Integer rootId,
- Map<String, Object> headers) {
- boolean standalone = request.getDeploymentConfiguration().isStandalone(
- request);
- Document document;
- Element applicationTag;
- if (standalone) {
- document = Document.createShell("");
- applicationTag = document.body();
- } else {
- document = null;
- applicationTag = new Element(Tag.valueOf("div"), "");
- }
- BootstrapContext context = new BootstrapContext(response,
- new BootstrapResponse(this, request, document, applicationTag,
- headers, application, rootId));
- return context;
- }
-
- protected String getMainDivStyle(BootstrapContext context) {
- return null;
- }
-
- /**
- * Creates and returns a unique ID for the DIV where the application is to
- * be rendered.
- *
- * @param context
- *
- * @return the id to use in the DOM
- */
- protected abstract String getApplicationId(BootstrapContext context);
-
- public String getWidgetsetForRoot(BootstrapContext context) {
- Root root = context.getRoot();
- WrappedRequest request = context.getRequest();
-
- String widgetset = root.getApplication().getWidgetsetForRoot(root);
- if (widgetset == null) {
- widgetset = request.getDeploymentConfiguration()
- .getConfiguredWidgetset(request);
- }
-
- widgetset = AbstractApplicationServlet.stripSpecialChars(widgetset);
- return widgetset;
- }
-
- /**
- * 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 context
- *
- * @throws IOException
- */
- protected void setMainDiv(BootstrapContext context) throws IOException {
- String style = getMainDivStyle(context);
-
- /*- Add classnames;
- * .v-app
- * .v-app-loading
- * .v-app-<simpleName for app class>
- *- Additionally added from javascript:
- * .v-theme-<themeName, remove non-alphanum>
- */
-
- String appClass = "v-app-"
- + getApplicationCSSClassName(context.getApplication());
-
- String classNames = "v-app " + appClass;
-
- Element applicationTag = context.getBootstrapResponse()
- .getApplicationTag();
- Element mainDiv = applicationTag.appendElement("div");
- mainDiv.attr("id", context.getAppId());
- mainDiv.addClass(classNames);
- if (style != null && style.length() != 0) {
- mainDiv.attr("style", style);
- }
- mainDiv.appendElement("div").addClass("v-app-loading");
- mainDiv.appendElement("noscript").append(getNoScriptMessage());
- }
-
- /**
- * Returns a message printed for browsers without scripting support or if
- * browsers scripting support is disabled.
- */
- protected String getNoScriptMessage() {
- return "You have to enable javascript in your browser to use an application built with Vaadin.";
- }
-
- /**
- * Returns the application class identifier for use in the application CSS
- * class name in the root DIV. The application CSS class name is of form
- * "v-app-"+getApplicationCSSClassName().
- *
- * This method should normally not be overridden.
- *
- * @return The CSS class name to use in combination with "v-app-".
- */
- protected String getApplicationCSSClassName(Application application) {
- return application.getClass().getSimpleName();
- }
-
- /**
- *
- * Method to open the body tag of the html kickstart page.
- * <p>
- * This method is responsible for closing the head tag and opening the body
- * tag.
- * <p>
- * Override this method if you want to add some custom html to the page.
- *
- * @throws IOException
- */
- protected void setBodyTag(BootstrapContext context) throws IOException {
- Element body = context.getBootstrapResponse().getDocument().body();
- body.attr("scroll", "auto");
- body.addClass(ApplicationConnection.GENERATED_BODY_CLASSNAME);
- }
-
- /**
- * Method to write the script part of the page which loads needed Vaadin
- * scripts and themes.
- * <p>
- * Override this method if you want to add some custom html around scripts.
- *
- * @param context
- *
- * @throws IOException
- * @throws JSONException
- */
- protected void setBootstrapPageHtmlVaadinScripts(BootstrapContext context)
- throws IOException, JSONException {
- WrappedRequest request = context.getRequest();
-
- DeploymentConfiguration deploymentConfiguration = request
- .getDeploymentConfiguration();
- String staticFileLocation = deploymentConfiguration
- .getStaticFileLocation(request);
-
- Element applicationTag = context.getBootstrapResponse()
- .getApplicationTag();
-
- applicationTag
- .appendElement("iframe")
- .attr("tabIndex", "-1")
- .attr("id", "__gwt_historyFrame")
- .attr("style",
- "position:absolute;width:0;height:0;border:0;overflow:hidden")
- .attr("src", "javascript:false");
-
- String bootstrapLocation = staticFileLocation
- + "/VAADIN/vaadinBootstrap.js";
- applicationTag.appendElement("script").attr("type", "text/javascript")
- .attr("src", bootstrapLocation);
- Element mainScriptTag = applicationTag.appendElement("script").attr(
- "type", "text/javascript");
-
- StringBuilder builder = new StringBuilder();
- builder.append("//<![CDATA[\n");
- builder.append("if (!window.vaadin) alert("
- + JSONObject.quote("Failed to load the bootstrap javascript: "
- + bootstrapLocation) + ");\n");
-
- appendMainScriptTagContents(context, builder);
-
- builder.append("//]]>");
- mainScriptTag.appendChild(new DataNode(builder.toString(),
- mainScriptTag.baseUri()));
- }
-
- protected void appendMainScriptTagContents(BootstrapContext context,
- StringBuilder builder) throws JSONException, IOException {
- JSONObject defaults = getDefaultParameters(context);
- JSONObject appConfig = getApplicationParameters(context);
-
- boolean isDebug = !context.getApplication().isProductionMode();
-
- builder.append("vaadin.setDefaults(");
- appendJsonObject(builder, defaults, isDebug);
- builder.append(");\n");
-
- builder.append("vaadin.initApplication(\"");
- builder.append(context.getAppId());
- builder.append("\",");
- appendJsonObject(builder, appConfig, isDebug);
- builder.append(");\n");
- }
-
- private static void appendJsonObject(StringBuilder builder,
- JSONObject jsonObject, boolean isDebug) throws JSONException {
- if (isDebug) {
- builder.append(jsonObject.toString(4));
- } else {
- builder.append(jsonObject.toString());
- }
- }
-
- protected JSONObject getApplicationParameters(BootstrapContext context)
- throws JSONException, PaintException {
- Application application = context.getApplication();
- Integer rootId = context.getRootId();
-
- JSONObject appConfig = new JSONObject();
-
- if (rootId != null) {
- appConfig.put(ApplicationConnection.ROOT_ID_PARAMETER, rootId);
- }
-
- if (context.getThemeName() != null) {
- appConfig.put("themeUri",
- getThemeUri(context, context.getThemeName()));
- }
-
- JSONObject versionInfo = new JSONObject();
- versionInfo.put("vaadinVersion", Version.getFullVersion());
- versionInfo.put("applicationVersion", application.getVersion());
- appConfig.put("versionInfo", versionInfo);
-
- appConfig.put("widgetset", context.getWidgetsetName());
-
- if (rootId == null || application.isRootInitPending(rootId.intValue())) {
- appConfig.put("initialPath", context.getRequest()
- .getRequestPathInfo());
-
- Map<String, String[]> parameterMap = context.getRequest()
- .getParameterMap();
- appConfig.put("initialParams", parameterMap);
- } else {
- // write the initial UIDL into the config
- appConfig.put("uidl",
- getInitialUIDL(context.getRequest(), context.getRoot()));
- }
-
- return appConfig;
- }
-
- protected JSONObject getDefaultParameters(BootstrapContext context)
- throws JSONException {
- JSONObject defaults = new JSONObject();
-
- WrappedRequest request = context.getRequest();
- Application application = context.getApplication();
-
- // Get system messages
- Application.SystemMessages systemMessages = AbstractApplicationServlet
- .getSystemMessages(application.getClass());
- if (systemMessages != null) {
- // Write the CommunicationError -message to client
- JSONObject comErrMsg = new JSONObject();
- comErrMsg.put("caption",
- systemMessages.getCommunicationErrorCaption());
- comErrMsg.put("message",
- systemMessages.getCommunicationErrorMessage());
- comErrMsg.put("url", systemMessages.getCommunicationErrorURL());
-
- defaults.put("comErrMsg", comErrMsg);
-
- JSONObject authErrMsg = new JSONObject();
- authErrMsg.put("caption",
- systemMessages.getAuthenticationErrorCaption());
- authErrMsg.put("message",
- systemMessages.getAuthenticationErrorMessage());
- authErrMsg.put("url", systemMessages.getAuthenticationErrorURL());
-
- defaults.put("authErrMsg", authErrMsg);
- }
-
- DeploymentConfiguration deploymentConfiguration = request
- .getDeploymentConfiguration();
- String staticFileLocation = deploymentConfiguration
- .getStaticFileLocation(request);
- String widgetsetBase = staticFileLocation + "/"
- + AbstractApplicationServlet.WIDGETSET_DIRECTORY_PATH;
- defaults.put("widgetsetBase", widgetsetBase);
-
- if (!application.isProductionMode()) {
- defaults.put("debug", true);
- }
-
- if (deploymentConfiguration.isStandalone(request)) {
- defaults.put("standalone", true);
- }
-
- defaults.put("appUri", getAppUri(context));
-
- return defaults;
- }
-
- protected abstract String getAppUri(BootstrapContext context);
-
- /**
- * Method to write the contents of head element in html kickstart page.
- * <p>
- * Override this method if you want to add some custom html to the header of
- * the page.
- *
- * @throws IOException
- */
- protected void setBootstrapPageHtmlHeader(BootstrapContext context)
- throws IOException {
- String themeName = context.getThemeName();
- Element head = context.getBootstrapResponse().getDocument().head();
- head.appendElement("meta").attr("http-equiv", "Content-Type")
- .attr("content", "text/html; charset=utf-8");
-
- // Chrome frame in all versions of IE (only if Chrome frame is
- // installed)
- head.appendElement("meta").attr("http-equiv", "X-UA-Compatible")
- .attr("content", "chrome=1");
-
- head.appendElement("style").attr("type", "text/css")
- .appendText("html, body {height:100%;margin:0;}");
-
- // Add favicon links
- if (themeName != null) {
- String themeUri = getThemeUri(context, themeName);
- head.appendElement("link").attr("rel", "shortcut icon")
- .attr("type", "image/vnd.microsoft.icon")
- .attr("href", themeUri + "/favicon.ico");
- head.appendElement("link").attr("rel", "icon")
- .attr("type", "image/vnd.microsoft.icon")
- .attr("href", themeUri + "/favicon.ico");
- }
-
- Root root = context.getRoot();
- String title = ((root == null || root.getCaption() == null) ? "" : root
- .getCaption());
-
- head.appendElement("title").appendText(title);
- }
-
- /**
- * Method to set http request headers for the Vaadin kickstart page.
- * <p>
- * Override this method if you need to customize http headers of the page.
- *
- * @param context
- */
- protected void setBootstrapPageHeaders(BootstrapContext context) {
- WrappedResponse response = context.getResponse();
-
- // Window renders are not cacheable
- response.setHeader("Cache-Control", "no-cache");
- response.setHeader("Pragma", "no-cache");
- response.setDateHeader("Expires", 0);
- response.setContentType("text/html; charset=UTF-8");
- }
-
- /**
- * Method to write the beginning of the html page.
- * <p>
- * This method is responsible for writing appropriate doc type declarations
- * and to open html and head tags.
- * <p>
- * Override this method if you want to add some custom html to the very
- * beginning of the page.
- *
- * @param context
- * @throws IOException
- */
- protected void setBasicHtml(BootstrapContext context) throws IOException {
-
- // write html header
- // page.write("<!DOCTYPE html PUBLIC \"-//W3C//DTD "
- // + "XHTML 1.0 Transitional//EN\" "
- // + "\"http://www.w3.org/TR/xhtml1/"
- // + "DTD/xhtml1-transitional.dtd\">\n");
- Document document = context.getBootstrapResponse().getDocument();
- DocumentType doctype = new DocumentType("html",
- "//W3C//DTD XHTML 1.0 Transitional//EN",
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd",
- document.baseUri());
- document.child(0).before(doctype);
-
- document.body().parent().attr("xmlns", "http://www.w3.org/1999/xhtml");
- }
-
- /**
- * Get the URI for the application theme.
- *
- * A portal-wide default theme is fetched from the portal shared resource
- * directory (if any), other themes from the portlet.
- *
- * @param context
- * @param themeName
- *
- * @return
- */
- public String getThemeUri(BootstrapContext context, String themeName) {
- WrappedRequest request = context.getRequest();
- final String staticFilePath = request.getDeploymentConfiguration()
- .getStaticFileLocation(request);
- return staticFilePath + "/"
- + AbstractApplicationServlet.THEME_DIRECTORY_PATH + themeName;
- }
-
- /**
- * Override if required
- *
- * @param context
- * @return
- */
- public String getThemeName(BootstrapContext context) {
- return context.getApplication().getThemeForRoot(context.getRoot());
- }
-
- /**
- * Don not override.
- *
- * @param context
- * @return
- */
- public String findAndEscapeThemeName(BootstrapContext context) {
- String themeName = getThemeName(context);
- if (themeName == null) {
- WrappedRequest request = context.getRequest();
- themeName = request.getDeploymentConfiguration()
- .getConfiguredTheme(request);
- }
-
- // XSS preventation, theme names shouldn't contain special chars anyway.
- // The servlet denies them via url parameter.
- themeName = AbstractApplicationServlet.stripSpecialChars(themeName);
-
- return themeName;
- }
-
- protected void writeError(WrappedResponse response, Throwable e)
- throws IOException {
- response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
- e.getLocalizedMessage());
- }
-
- /**
- * Gets the initial UIDL message to send to the client.
- *
- * @param request
- * the originating request
- * @param root
- * the root for which the UIDL should be generated
- * @return a string with the initial UIDL message
- * @throws PaintException
- * if an exception occurs while painting the components
- * @throws JSONException
- * if an exception occurs while formatting the output
- */
- protected abstract String getInitialUIDL(WrappedRequest request, Root root)
- throws PaintException, JSONException;
-
-}
diff --git a/src/com/vaadin/terminal/gwt/server/BootstrapListener.java b/src/com/vaadin/terminal/gwt/server/BootstrapListener.java
deleted file mode 100644
index 54bd13c25a..0000000000
--- a/src/com/vaadin/terminal/gwt/server/BootstrapListener.java
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal.gwt.server;
-
-import java.util.EventListener;
-
-public interface BootstrapListener extends EventListener {
- public void modifyBootstrap(BootstrapResponse response);
-}
diff --git a/src/com/vaadin/terminal/gwt/server/BootstrapResponse.java b/src/com/vaadin/terminal/gwt/server/BootstrapResponse.java
deleted file mode 100644
index 37b59989f6..0000000000
--- a/src/com/vaadin/terminal/gwt/server/BootstrapResponse.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal.gwt.server;
-
-import java.util.EventObject;
-import java.util.Map;
-
-import org.jsoup.nodes.Document;
-import org.jsoup.nodes.Element;
-
-import com.vaadin.Application;
-import com.vaadin.terminal.WrappedRequest;
-import com.vaadin.ui.Root;
-
-public class BootstrapResponse extends EventObject {
- private final Document document;
- private final WrappedRequest request;
- private final Map<String, Object> headers;
- private final Element applicationTag;
- private final Application application;
- private final Integer rootId;
-
- public BootstrapResponse(BootstrapHandler handler, WrappedRequest request,
- Document document, Element applicationTag,
- Map<String, Object> headers, Application application, Integer rootId) {
- super(handler);
- this.request = request;
- this.document = document;
- this.applicationTag = applicationTag;
- this.headers = headers;
- this.application = application;
- this.rootId = rootId;
- }
-
- public void setHeader(String name, String value) {
- headers.put(name, value);
- }
-
- public void setDateHeader(String name, long timestamp) {
- headers.put(name, Long.valueOf(timestamp));
- }
-
- public BootstrapHandler getBootstrapHandler() {
- return (BootstrapHandler) getSource();
- }
-
- public WrappedRequest getRequest() {
- return request;
- }
-
- public Document getDocument() {
- return document;
- }
-
- public Element getApplicationTag() {
- return applicationTag;
- }
-
- public Application getApplication() {
- return application;
- }
-
- public Integer getRootId() {
- return rootId;
- }
-
- public Root getRoot() {
- return Root.getCurrent();
- }
-}
diff --git a/src/com/vaadin/terminal/gwt/server/ChangeVariablesErrorEvent.java b/src/com/vaadin/terminal/gwt/server/ChangeVariablesErrorEvent.java
deleted file mode 100644
index 8f0c80332f..0000000000
--- a/src/com/vaadin/terminal/gwt/server/ChangeVariablesErrorEvent.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.terminal.gwt.server;
-
-import java.util.Map;
-
-import com.vaadin.ui.AbstractComponent.ComponentErrorEvent;
-import com.vaadin.ui.Component;
-
-@SuppressWarnings("serial")
-public class ChangeVariablesErrorEvent implements ComponentErrorEvent {
-
- private Throwable throwable;
- private Component component;
-
- private Map<String, Object> variableChanges;
-
- public ChangeVariablesErrorEvent(Component component, Throwable throwable,
- Map<String, Object> variableChanges) {
- this.component = component;
- this.throwable = throwable;
- this.variableChanges = variableChanges;
- }
-
- @Override
- public Throwable getThrowable() {
- return throwable;
- }
-
- public Component getComponent() {
- return component;
- }
-
- public Map<String, Object> getVariableChanges() {
- return variableChanges;
- }
-
-} \ No newline at end of file
diff --git a/src/com/vaadin/terminal/gwt/server/ClientConnector.java b/src/com/vaadin/terminal/gwt/server/ClientConnector.java
deleted file mode 100644
index 4f74cfe4bb..0000000000
--- a/src/com/vaadin/terminal/gwt/server/ClientConnector.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.terminal.gwt.server;
-
-import java.util.Collection;
-import java.util.List;
-
-import com.vaadin.shared.Connector;
-import com.vaadin.shared.communication.SharedState;
-import com.vaadin.terminal.AbstractClientConnector;
-import com.vaadin.terminal.Extension;
-import com.vaadin.ui.Component;
-import com.vaadin.ui.ComponentContainer;
-import com.vaadin.ui.Root;
-
-/**
- * Interface implemented by all connectors that are capable of communicating
- * with the client side
- *
- * @author Vaadin Ltd
- * @version @VERSION@
- * @since 7.0.0
- *
- */
-public interface ClientConnector extends Connector, RpcTarget {
- /**
- * Returns the list of pending server to client RPC calls and clears the
- * list.
- *
- * @return an unmodifiable ordered list of pending server to client method
- * calls (not null)
- */
- public List<ClientMethodInvocation> retrievePendingRpcCalls();
-
- /**
- * Checks if the communicator is enabled. An enabled communicator is allowed
- * to receive messages from its counter-part.
- *
- * @return true if the connector can receive messages, false otherwise
- */
- public boolean isConnectorEnabled();
-
- /**
- * Returns the type of the shared state for this connector
- *
- * @return The type of the state. Must never return null.
- */
- public Class<? extends SharedState> getStateType();
-
- @Override
- public ClientConnector getParent();
-
- /**
- * Requests that the connector should be repainted as soon as possible.
- */
- public void requestRepaint();
-
- /**
- * Causes a repaint of this connector, and all connectors below it.
- *
- * This should only be used in special cases, e.g when the state of a
- * descendant depends on the state of an ancestor.
- */
- public void requestRepaintAll();
-
- /**
- * Sets the parent connector of the connector.
- *
- * <p>
- * This method automatically calls {@link #attach()} if the connector
- * becomes attached to the application, regardless of whether it was
- * attached previously. Conversely, if the parent is {@code null} and the
- * connector is attached to the application, {@link #detach()} is called for
- * the connector.
- * </p>
- * <p>
- * This method is rarely called directly. One of the
- * {@link ComponentContainer#addComponent(Component)} or
- * {@link AbstractClientConnector#addExtension(Extension)} methods are
- * normally used for adding connectors to a parent and they will call this
- * method implicitly.
- * </p>
- *
- * <p>
- * It is not possible to change the parent without first setting the parent
- * to {@code null}.
- * </p>
- *
- * @param parent
- * the parent connector
- * @throws IllegalStateException
- * if a parent is given even though the connector already has a
- * parent
- */
- public void setParent(ClientConnector parent);
-
- /**
- * Notifies the connector that it is connected to an application.
- *
- * <p>
- * The caller of this method is {@link #setParent(ClientConnector)} if the
- * parent is itself already attached to the application. If not, the parent
- * will call the {@link #attach()} for all its children when it is attached
- * to the application. This method is always called before the connector's
- * data is sent to the client-side for the first time.
- * </p>
- *
- * <p>
- * The attachment logic is implemented in {@link AbstractClientConnector}.
- * </p>
- */
- public void attach();
-
- /**
- * Notifies the component that it is detached from the application.
- *
- * <p>
- * The caller of this method is {@link #setParent(ClientConnector)} if the
- * parent is in the application. When the parent is detached from the
- * application it is its response to call {@link #detach()} for all the
- * children and to detach itself from the terminal.
- * </p>
- */
- public void detach();
-
- /**
- * Get a read-only collection of all extensions attached to this connector.
- *
- * @return a collection of extensions
- */
- public Collection<Extension> getExtensions();
-
- /**
- * Remove an extension from this connector.
- *
- * @param extension
- * the extension to remove.
- */
- public void removeExtension(Extension extension);
-
- /**
- * Returns the root this connector is attached to
- *
- * @return The Root this connector is attached to or null if it is not
- * attached to any Root
- */
- public Root getRoot();
-}
diff --git a/src/com/vaadin/terminal/gwt/server/ClientMethodInvocation.java b/src/com/vaadin/terminal/gwt/server/ClientMethodInvocation.java
deleted file mode 100644
index 64ea288665..0000000000
--- a/src/com/vaadin/terminal/gwt/server/ClientMethodInvocation.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal.gwt.server;
-
-import java.io.Serializable;
-import java.lang.reflect.Method;
-import java.lang.reflect.Type;
-
-/**
- * Internal class for keeping track of pending server to client method
- * invocations for a Connector.
- *
- * @since 7.0
- */
-public class ClientMethodInvocation implements Serializable,
- Comparable<ClientMethodInvocation> {
- private final ClientConnector connector;
- private final String interfaceName;
- private final String methodName;
- private final Object[] parameters;
- private Type[] parameterTypes;
-
- // used for sorting calls between different connectors in the same Root
- private final long sequenceNumber;
- // TODO may cause problems when clustering etc.
- private static long counter = 0;
-
- public ClientMethodInvocation(ClientConnector connector,
- String interfaceName, Method method, Object[] parameters) {
- this.connector = connector;
- this.interfaceName = interfaceName;
- methodName = method.getName();
- parameterTypes = method.getGenericParameterTypes();
- this.parameters = (null != parameters) ? parameters : new Object[0];
- sequenceNumber = ++counter;
- }
-
- public Type[] getParameterTypes() {
- return parameterTypes;
- }
-
- public ClientConnector getConnector() {
- return connector;
- }
-
- public String getInterfaceName() {
- return interfaceName;
- }
-
- public String getMethodName() {
- return methodName;
- }
-
- public Object[] getParameters() {
- return parameters;
- }
-
- protected long getSequenceNumber() {
- return sequenceNumber;
- }
-
- @Override
- public int compareTo(ClientMethodInvocation o) {
- if (null == o) {
- return 0;
- }
- return Long.signum(getSequenceNumber() - o.getSequenceNumber());
- }
-} \ No newline at end of file
diff --git a/src/com/vaadin/terminal/gwt/server/CommunicationManager.java b/src/com/vaadin/terminal/gwt/server/CommunicationManager.java
deleted file mode 100644
index 3cc3a8cb64..0000000000
--- a/src/com/vaadin/terminal/gwt/server/CommunicationManager.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal.gwt.server;
-
-import java.io.InputStream;
-import java.net.URL;
-
-import javax.servlet.ServletContext;
-
-import com.vaadin.Application;
-import com.vaadin.external.json.JSONException;
-import com.vaadin.terminal.PaintException;
-import com.vaadin.terminal.WrappedRequest;
-import com.vaadin.ui.Root;
-
-/**
- * Application manager processes changes and paints for single application
- * instance.
- *
- * This class handles applications running as servlets.
- *
- * @see AbstractCommunicationManager
- *
- * @author Vaadin Ltd.
- * @version
- * @VERSION@
- * @since 5.0
- */
-@SuppressWarnings("serial")
-public class CommunicationManager extends AbstractCommunicationManager {
-
- /**
- * @deprecated use {@link #CommunicationManager(Application)} instead
- * @param application
- * @param applicationServlet
- */
- @Deprecated
- public CommunicationManager(Application application,
- AbstractApplicationServlet applicationServlet) {
- super(application);
- }
-
- /**
- * TODO New constructor - document me!
- *
- * @param application
- */
- public CommunicationManager(Application application) {
- super(application);
- }
-
- @Override
- protected BootstrapHandler createBootstrapHandler() {
- return new BootstrapHandler() {
- @Override
- protected String getApplicationId(BootstrapContext context) {
- String appUrl = getAppUri(context);
-
- String appId = appUrl;
- if ("".equals(appUrl)) {
- appId = "ROOT";
- }
- appId = appId.replaceAll("[^a-zA-Z0-9]", "");
- // Add hashCode to the end, so that it is still (sort of)
- // predictable, but indicates that it should not be used in CSS
- // and
- // such:
- int hashCode = appId.hashCode();
- if (hashCode < 0) {
- hashCode = -hashCode;
- }
- appId = appId + "-" + hashCode;
- return appId;
- }
-
- @Override
- protected String getAppUri(BootstrapContext context) {
- /* Fetch relative url to application */
- // don't use server and port in uri. It may cause problems with
- // some
- // virtual server configurations which lose the server name
- Application application = context.getApplication();
- URL url = application.getURL();
- String appUrl = url.getPath();
- if (appUrl.endsWith("/")) {
- appUrl = appUrl.substring(0, appUrl.length() - 1);
- }
- return appUrl;
- }
-
- @Override
- public String getThemeName(BootstrapContext context) {
- String themeName = context.getRequest().getParameter(
- AbstractApplicationServlet.URL_PARAMETER_THEME);
- if (themeName == null) {
- themeName = super.getThemeName(context);
- }
- return themeName;
- }
-
- @Override
- protected String getInitialUIDL(WrappedRequest request, Root root)
- throws PaintException, JSONException {
- return CommunicationManager.this.getInitialUIDL(request, root);
- }
- };
- }
-
- @Override
- protected InputStream getThemeResourceAsStream(Root root, String themeName,
- String resource) {
- WebApplicationContext context = (WebApplicationContext) root
- .getApplication().getContext();
- ServletContext servletContext = context.getHttpSession()
- .getServletContext();
- return servletContext.getResourceAsStream("/"
- + AbstractApplicationServlet.THEME_DIRECTORY_PATH + themeName
- + "/" + resource);
- }
-}
diff --git a/src/com/vaadin/terminal/gwt/server/ComponentSizeValidator.java b/src/com/vaadin/terminal/gwt/server/ComponentSizeValidator.java
deleted file mode 100644
index 171d440796..0000000000
--- a/src/com/vaadin/terminal/gwt/server/ComponentSizeValidator.java
+++ /dev/null
@@ -1,664 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.terminal.gwt.server;
-
-import java.io.PrintStream;
-import java.io.PrintWriter;
-import java.io.Serializable;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Stack;
-import java.util.Vector;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.vaadin.terminal.Sizeable.Unit;
-import com.vaadin.ui.AbstractOrderedLayout;
-import com.vaadin.ui.AbstractSplitPanel;
-import com.vaadin.ui.Component;
-import com.vaadin.ui.ComponentContainer;
-import com.vaadin.ui.CustomComponent;
-import com.vaadin.ui.Form;
-import com.vaadin.ui.GridLayout;
-import com.vaadin.ui.GridLayout.Area;
-import com.vaadin.ui.Layout;
-import com.vaadin.ui.Panel;
-import com.vaadin.ui.TabSheet;
-import com.vaadin.ui.VerticalLayout;
-import com.vaadin.ui.Window;
-
-@SuppressWarnings({ "serial", "deprecation" })
-public class ComponentSizeValidator implements Serializable {
-
- private final static int LAYERS_SHOWN = 4;
-
- /**
- * Recursively checks given component and its subtree for invalid layout
- * setups. Prints errors to std err stream.
- *
- * @param component
- * component to check
- * @return set of first level errors found
- */
- public static List<InvalidLayout> validateComponentRelativeSizes(
- Component component, List<InvalidLayout> errors,
- InvalidLayout parent) {
-
- boolean invalidHeight = !checkHeights(component);
- boolean invalidWidth = !checkWidths(component);
-
- if (invalidHeight || invalidWidth) {
- InvalidLayout error = new InvalidLayout(component, invalidHeight,
- invalidWidth);
- if (parent != null) {
- parent.addError(error);
- } else {
- if (errors == null) {
- errors = new LinkedList<InvalidLayout>();
- }
- errors.add(error);
- }
- parent = error;
- }
-
- if (component instanceof Panel) {
- Panel panel = (Panel) component;
- errors = validateComponentRelativeSizes(panel.getContent(), errors,
- parent);
- } else if (component instanceof ComponentContainer) {
- ComponentContainer lo = (ComponentContainer) component;
- Iterator<Component> it = lo.getComponentIterator();
- while (it.hasNext()) {
- errors = validateComponentRelativeSizes(it.next(), errors,
- parent);
- }
- } else if (component instanceof Form) {
- Form form = (Form) component;
- if (form.getLayout() != null) {
- errors = validateComponentRelativeSizes(form.getLayout(),
- errors, parent);
- }
- if (form.getFooter() != null) {
- errors = validateComponentRelativeSizes(form.getFooter(),
- errors, parent);
- }
- }
-
- return errors;
- }
-
- private static void printServerError(String msg,
- Stack<ComponentInfo> attributes, boolean widthError,
- PrintStream errorStream) {
- StringBuffer err = new StringBuffer();
- err.append("Vaadin DEBUG\n");
-
- StringBuilder indent = new StringBuilder("");
- ComponentInfo ci;
- if (attributes != null) {
- while (attributes.size() > LAYERS_SHOWN) {
- attributes.pop();
- }
- while (!attributes.empty()) {
- ci = attributes.pop();
- showComponent(ci.component, ci.info, err, indent, widthError);
- }
- }
-
- err.append("Layout problem detected: ");
- err.append(msg);
- err.append("\n");
- err.append("Relative sizes were replaced by undefined sizes, components may not render as expected.\n");
- errorStream.println(err);
-
- }
-
- public static boolean checkHeights(Component component) {
- try {
- if (!hasRelativeHeight(component)) {
- return true;
- }
- if (component instanceof Window) {
- return true;
- }
- if (component.getParent() == null) {
- return true;
- }
-
- return parentCanDefineHeight(component);
- } catch (Exception e) {
- getLogger().log(Level.FINER,
- "An exception occurred while validating sizes.", e);
- return true;
- }
- }
-
- public static boolean checkWidths(Component component) {
- try {
- if (!hasRelativeWidth(component)) {
- return true;
- }
- if (component instanceof Window) {
- return true;
- }
- if (component.getParent() == null) {
- return true;
- }
-
- return parentCanDefineWidth(component);
- } catch (Exception e) {
- getLogger().log(Level.FINER,
- "An exception occurred while validating sizes.", e);
- return true;
- }
- }
-
- public static class InvalidLayout implements Serializable {
-
- private final Component component;
-
- private final boolean invalidHeight;
- private final boolean invalidWidth;
-
- private final Vector<InvalidLayout> subErrors = new Vector<InvalidLayout>();
-
- public InvalidLayout(Component component, boolean height, boolean width) {
- this.component = component;
- invalidHeight = height;
- invalidWidth = width;
- }
-
- public void addError(InvalidLayout error) {
- subErrors.add(error);
- }
-
- public void reportErrors(PrintWriter clientJSON,
- AbstractCommunicationManager communicationManager,
- PrintStream serverErrorStream) {
- clientJSON.write("{");
-
- Component parent = component.getParent();
- String paintableId = component.getConnectorId();
-
- clientJSON.print("id:\"" + paintableId + "\"");
-
- if (invalidHeight) {
- Stack<ComponentInfo> attributes = null;
- String msg = "";
- // set proper error messages
- if (parent instanceof AbstractOrderedLayout) {
- AbstractOrderedLayout ol = (AbstractOrderedLayout) parent;
- boolean vertical = false;
-
- if (ol instanceof VerticalLayout) {
- vertical = true;
- }
-
- if (vertical) {
- msg = "Component with relative height inside a VerticalLayout with no height defined.";
- attributes = getHeightAttributes(component);
- } else {
- msg = "At least one of a HorizontalLayout's components must have non relative height if the height of the layout is not defined";
- attributes = getHeightAttributes(component);
- }
- } else if (parent instanceof GridLayout) {
- msg = "At least one of the GridLayout's components in each row should have non relative height if the height of the layout is not defined.";
- attributes = getHeightAttributes(component);
- } else {
- // default error for non sized parent issue
- msg = "A component with relative height needs a parent with defined height.";
- attributes = getHeightAttributes(component);
- }
- printServerError(msg, attributes, false, serverErrorStream);
- clientJSON.print(",\"heightMsg\":\"" + msg + "\"");
- }
- if (invalidWidth) {
- Stack<ComponentInfo> attributes = null;
- String msg = "";
- if (parent instanceof AbstractOrderedLayout) {
- AbstractOrderedLayout ol = (AbstractOrderedLayout) parent;
- boolean horizontal = true;
-
- if (ol instanceof VerticalLayout) {
- horizontal = false;
- }
-
- if (horizontal) {
- msg = "Component with relative width inside a HorizontalLayout with no width defined";
- attributes = getWidthAttributes(component);
- } else {
- msg = "At least one of a VerticalLayout's components must have non relative width if the width of the layout is not defined";
- attributes = getWidthAttributes(component);
- }
- } else if (parent instanceof GridLayout) {
- msg = "At least one of the GridLayout's components in each column should have non relative width if the width of the layout is not defined.";
- attributes = getWidthAttributes(component);
- } else {
- // default error for non sized parent issue
- msg = "A component with relative width needs a parent with defined width.";
- attributes = getWidthAttributes(component);
- }
- clientJSON.print(",\"widthMsg\":\"" + msg + "\"");
- printServerError(msg, attributes, true, serverErrorStream);
- }
- if (subErrors.size() > 0) {
- serverErrorStream.println("Sub errors >>");
- clientJSON.write(", \"subErrors\" : [");
- boolean first = true;
- for (InvalidLayout subError : subErrors) {
- if (!first) {
- clientJSON.print(",");
- } else {
- first = false;
- }
- subError.reportErrors(clientJSON, communicationManager,
- serverErrorStream);
- }
- clientJSON.write("]");
- serverErrorStream.println("<< Sub erros");
- }
- clientJSON.write("}");
- }
- }
-
- private static class ComponentInfo implements Serializable {
- Component component;
- String info;
-
- public ComponentInfo(Component component, String info) {
- this.component = component;
- this.info = info;
- }
-
- }
-
- private static Stack<ComponentInfo> getHeightAttributes(Component component) {
- Stack<ComponentInfo> attributes = new Stack<ComponentInfo>();
- attributes
- .add(new ComponentInfo(component, getHeightString(component)));
- Component parent = component.getParent();
- attributes.add(new ComponentInfo(parent, getHeightString(parent)));
-
- while ((parent = parent.getParent()) != null) {
- attributes.add(new ComponentInfo(parent, getHeightString(parent)));
- }
-
- return attributes;
- }
-
- private static Stack<ComponentInfo> getWidthAttributes(Component component) {
- Stack<ComponentInfo> attributes = new Stack<ComponentInfo>();
- attributes.add(new ComponentInfo(component, getWidthString(component)));
- Component parent = component.getParent();
- attributes.add(new ComponentInfo(parent, getWidthString(parent)));
-
- while ((parent = parent.getParent()) != null) {
- attributes.add(new ComponentInfo(parent, getWidthString(parent)));
- }
-
- return attributes;
- }
-
- private static String getWidthString(Component component) {
- String width = "width: ";
- if (hasRelativeWidth(component)) {
- width += "RELATIVE, " + component.getWidth() + " %";
- } else if (component instanceof Window && component.getParent() == null) {
- width += "MAIN WINDOW";
- } else if (component.getWidth() >= 0) {
- width += "ABSOLUTE, " + component.getWidth() + " "
- + component.getWidthUnits().getSymbol();
- } else {
- width += "UNDEFINED";
- }
-
- return width;
- }
-
- private static String getHeightString(Component component) {
- String height = "height: ";
- if (hasRelativeHeight(component)) {
- height += "RELATIVE, " + component.getHeight() + " %";
- } else if (component instanceof Window && component.getParent() == null) {
- height += "MAIN WINDOW";
- } else if (component.getHeight() > 0) {
- height += "ABSOLUTE, " + component.getHeight() + " "
- + component.getHeightUnits().getSymbol();
- } else {
- height += "UNDEFINED";
- }
-
- return height;
- }
-
- private static void showComponent(Component component, String attribute,
- StringBuffer err, StringBuilder indent, boolean widthError) {
-
- FileLocation createLoc = creationLocations.get(component);
-
- FileLocation sizeLoc;
- if (widthError) {
- sizeLoc = widthLocations.get(component);
- } else {
- sizeLoc = heightLocations.get(component);
- }
-
- err.append(indent);
- indent.append(" ");
- err.append("- ");
-
- err.append(component.getClass().getSimpleName());
- err.append("/").append(Integer.toHexString(component.hashCode()));
-
- if (component.getCaption() != null) {
- err.append(" \"");
- err.append(component.getCaption());
- err.append("\"");
- }
-
- if (component.getDebugId() != null) {
- err.append(" debugId: ");
- err.append(component.getDebugId());
- }
-
- if (createLoc != null) {
- err.append(", created at (" + createLoc.file + ":"
- + createLoc.lineNumber + ")");
-
- }
-
- if (attribute != null) {
- err.append(" (");
- err.append(attribute);
- if (sizeLoc != null) {
- err.append(", set at (" + sizeLoc.file + ":"
- + sizeLoc.lineNumber + ")");
- }
-
- err.append(")");
- }
- err.append("\n");
-
- }
-
- private static boolean hasNonRelativeHeightComponent(
- AbstractOrderedLayout ol) {
- Iterator<Component> it = ol.getComponentIterator();
- while (it.hasNext()) {
- if (!hasRelativeHeight(it.next())) {
- return true;
- }
- }
- return false;
- }
-
- public static boolean parentCanDefineHeight(Component component) {
- Component parent = component.getParent();
- if (parent == null) {
- // main window, valid situation
- return true;
- }
- if (parent.getHeight() < 0) {
- // Undefined height
- if (parent instanceof Window) {
- // Sub window with undefined size has a min-height
- return true;
- }
-
- if (parent instanceof AbstractOrderedLayout) {
- boolean horizontal = true;
- if (parent instanceof VerticalLayout) {
- horizontal = false;
- }
- if (horizontal
- && hasNonRelativeHeightComponent((AbstractOrderedLayout) parent)) {
- return true;
- } else {
- return false;
- }
-
- } else if (parent instanceof GridLayout) {
- GridLayout gl = (GridLayout) parent;
- Area componentArea = gl.getComponentArea(component);
- boolean rowHasHeight = false;
- for (int row = componentArea.getRow1(); !rowHasHeight
- && row <= componentArea.getRow2(); row++) {
- for (int column = 0; !rowHasHeight
- && column < gl.getColumns(); column++) {
- Component c = gl.getComponent(column, row);
- if (c != null) {
- rowHasHeight = !hasRelativeHeight(c);
- }
- }
- }
- if (!rowHasHeight) {
- return false;
- } else {
- // Other components define row height
- return true;
- }
- }
-
- if (parent instanceof Panel || parent instanceof AbstractSplitPanel
- || parent instanceof TabSheet
- || parent instanceof CustomComponent) {
- // height undefined, we know how how component works and no
- // exceptions
- // TODO horiz SplitPanel ??
- return false;
- } else {
- // We cannot generally know if undefined component can serve
- // space for children (like CustomLayout or component built by
- // third party) so we assume they can
- return true;
- }
-
- } else if (hasRelativeHeight(parent)) {
- // Relative height
- if (parent.getParent() != null) {
- return parentCanDefineHeight(parent);
- } else {
- return true;
- }
- } else {
- // Absolute height
- return true;
- }
- }
-
- private static boolean hasRelativeHeight(Component component) {
- return (component.getHeightUnits() == Unit.PERCENTAGE && component
- .getHeight() > 0);
- }
-
- private static boolean hasNonRelativeWidthComponent(AbstractOrderedLayout ol) {
- Iterator<Component> it = ol.getComponentIterator();
- while (it.hasNext()) {
- if (!hasRelativeWidth(it.next())) {
- return true;
- }
- }
- return false;
- }
-
- private static boolean hasRelativeWidth(Component paintable) {
- return paintable.getWidth() > 0
- && paintable.getWidthUnits() == Unit.PERCENTAGE;
- }
-
- public static boolean parentCanDefineWidth(Component component) {
- Component parent = component.getParent();
- if (parent == null) {
- // main window, valid situation
- return true;
- }
- if (parent instanceof Window) {
- // Sub window with undefined size has a min-width
- return true;
- }
-
- if (parent.getWidth() < 0) {
- // Undefined width
-
- if (parent instanceof AbstractOrderedLayout) {
- AbstractOrderedLayout ol = (AbstractOrderedLayout) parent;
- boolean horizontal = true;
- if (ol instanceof VerticalLayout) {
- horizontal = false;
- }
-
- if (!horizontal && hasNonRelativeWidthComponent(ol)) {
- // valid situation, other components defined width
- return true;
- } else {
- return false;
- }
- } else if (parent instanceof GridLayout) {
- GridLayout gl = (GridLayout) parent;
- Area componentArea = gl.getComponentArea(component);
- boolean columnHasWidth = false;
- for (int col = componentArea.getColumn1(); !columnHasWidth
- && col <= componentArea.getColumn2(); col++) {
- for (int row = 0; !columnHasWidth && row < gl.getRows(); row++) {
- Component c = gl.getComponent(col, row);
- if (c != null) {
- columnHasWidth = !hasRelativeWidth(c);
- }
- }
- }
- if (!columnHasWidth) {
- return false;
- } else {
- // Other components define column width
- return true;
- }
- } else if (parent instanceof Form) {
- /*
- * If some other part of the form is not relative it determines
- * the component width
- */
- return hasNonRelativeWidthComponent((Form) parent);
- } else if (parent instanceof AbstractSplitPanel
- || parent instanceof TabSheet
- || parent instanceof CustomComponent) {
- // FIXME Could we use com.vaadin package name here and
- // fail for all component containers?
- // FIXME Actually this should be moved to containers so it can
- // be implemented for custom containers
- // TODO vertical splitpanel with another non relative component?
- return false;
- } else if (parent instanceof Window) {
- // Sub window can define width based on caption
- if (parent.getCaption() != null
- && !parent.getCaption().equals("")) {
- return true;
- } else {
- return false;
- }
- } else if (parent instanceof Panel) {
- // TODO Panel should be able to define width based on caption
- return false;
- } else {
- return true;
- }
- } else if (hasRelativeWidth(parent)) {
- // Relative width
- if (parent.getParent() == null) {
- return true;
- }
-
- return parentCanDefineWidth(parent);
- } else {
- return true;
- }
-
- }
-
- private static boolean hasNonRelativeWidthComponent(Form form) {
- Layout layout = form.getLayout();
- Layout footer = form.getFooter();
-
- if (layout != null && !hasRelativeWidth(layout)) {
- return true;
- }
- if (footer != null && !hasRelativeWidth(footer)) {
- return true;
- }
-
- return false;
- }
-
- private static Map<Object, FileLocation> creationLocations = new HashMap<Object, FileLocation>();
- private static Map<Object, FileLocation> widthLocations = new HashMap<Object, FileLocation>();
- private static Map<Object, FileLocation> heightLocations = new HashMap<Object, FileLocation>();
-
- public static class FileLocation implements Serializable {
- public String method;
- public String file;
- public String className;
- public String classNameSimple;
- public int lineNumber;
-
- public FileLocation(StackTraceElement traceElement) {
- file = traceElement.getFileName();
- className = traceElement.getClassName();
- classNameSimple = className
- .substring(className.lastIndexOf('.') + 1);
- lineNumber = traceElement.getLineNumber();
- method = traceElement.getMethodName();
- }
- }
-
- public static void setCreationLocation(Object object) {
- setLocation(creationLocations, object);
- }
-
- public static void setWidthLocation(Object object) {
- setLocation(widthLocations, object);
- }
-
- public static void setHeightLocation(Object object) {
- setLocation(heightLocations, object);
- }
-
- private static void setLocation(Map<Object, FileLocation> map, Object object) {
- StackTraceElement[] traceLines = Thread.currentThread().getStackTrace();
- for (StackTraceElement traceElement : traceLines) {
- Class<?> cls;
- try {
- String className = traceElement.getClassName();
- if (className.startsWith("java.")
- || className.startsWith("sun.")) {
- continue;
- }
-
- cls = Class.forName(className);
- if (cls == ComponentSizeValidator.class || cls == Thread.class) {
- continue;
- }
-
- if (Component.class.isAssignableFrom(cls)
- && !CustomComponent.class.isAssignableFrom(cls)) {
- continue;
- }
- FileLocation cl = new FileLocation(traceElement);
- map.put(object, cl);
- return;
- } catch (Exception e) {
- // TODO Auto-generated catch block
- getLogger().log(Level.FINER,
- "An exception occurred while validating sizes.", e);
- }
-
- }
- }
-
- private static Logger getLogger() {
- return Logger.getLogger(ComponentSizeValidator.class.getName());
- }
-
-}
diff --git a/src/com/vaadin/terminal/gwt/server/Constants.java b/src/com/vaadin/terminal/gwt/server/Constants.java
deleted file mode 100644
index 7efb0205ac..0000000000
--- a/src/com/vaadin/terminal/gwt/server/Constants.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.terminal.gwt.server;
-
-/**
- * TODO Document me!
- *
- * @author peholmst
- *
- */
-public interface Constants {
-
- static final String NOT_PRODUCTION_MODE_INFO = "\n"
- + "=================================================================\n"
- + "Vaadin is running in DEBUG MODE.\nAdd productionMode=true to web.xml "
- + "to disable debug features.\nTo show debug window, add ?debug to "
- + "your application URL.\n"
- + "=================================================================";
-
- static final String WARNING_XSRF_PROTECTION_DISABLED = "\n"
- + "===========================================================\n"
- + "WARNING: Cross-site request forgery protection is disabled!\n"
- + "===========================================================";
-
- static final String WARNING_RESOURCE_CACHING_TIME_NOT_NUMERIC = "\n"
- + "===========================================================\n"
- + "WARNING: resourceCacheTime has been set to a non integer value "
- + "in web.xml. The default of 1h will be used.\n"
- + "===========================================================";
-
- static final String WIDGETSET_MISMATCH_INFO = "\n"
- + "=================================================================\n"
- + "The widgetset in use does not seem to be built for the Vaadin\n"
- + "version in use. This might cause strange problems - a\n"
- + "recompile/deploy is strongly recommended.\n"
- + " Vaadin version: %s\n"
- + " Widgetset version: %s\n"
- + "=================================================================";
-
- static final String URL_PARAMETER_RESTART_APPLICATION = "restartApplication";
- static final String URL_PARAMETER_CLOSE_APPLICATION = "closeApplication";
- static final String URL_PARAMETER_REPAINT_ALL = "repaintAll";
- static final String URL_PARAMETER_THEME = "theme";
-
- static final String SERVLET_PARAMETER_PRODUCTION_MODE = "productionMode";
- static final String SERVLET_PARAMETER_DISABLE_XSRF_PROTECTION = "disable-xsrf-protection";
- static final String SERVLET_PARAMETER_RESOURCE_CACHE_TIME = "resourceCacheTime";
-
- // Configurable parameter names
- static final String PARAMETER_VAADIN_RESOURCES = "Resources";
-
- static final int DEFAULT_BUFFER_SIZE = 32 * 1024;
-
- static final int MAX_BUFFER_SIZE = 64 * 1024;
-
- final String THEME_DIRECTORY_PATH = "VAADIN/themes/";
-
- static final int DEFAULT_THEME_CACHETIME = 1000 * 60 * 60 * 24;
-
- static final String WIDGETSET_DIRECTORY_PATH = "VAADIN/widgetsets/";
-
- // Name of the default widget set, used if not specified in web.xml
- static final String DEFAULT_WIDGETSET = "com.vaadin.terminal.gwt.DefaultWidgetSet";
-
- // Widget set parameter name
- static final String PARAMETER_WIDGETSET = "widgetset";
-
- static final String ERROR_NO_ROOT_FOUND = "Application did not return a root for the request and did not request extra information either. Something is wrong.";
-
- static final String DEFAULT_THEME_NAME = "reindeer";
-
- static final String INVALID_SECURITY_KEY_MSG = "Invalid security key.";
-
- // portal configuration parameters
- static final String PORTAL_PARAMETER_VAADIN_WIDGETSET = "vaadin.widgetset";
- static final String PORTAL_PARAMETER_VAADIN_RESOURCE_PATH = "vaadin.resources.path";
- static final String PORTAL_PARAMETER_VAADIN_THEME = "vaadin.theme";
-
-}
diff --git a/src/com/vaadin/terminal/gwt/server/DragAndDropService.java b/src/com/vaadin/terminal/gwt/server/DragAndDropService.java
deleted file mode 100644
index efb5666efa..0000000000
--- a/src/com/vaadin/terminal/gwt/server/DragAndDropService.java
+++ /dev/null
@@ -1,313 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.terminal.gwt.server;
-
-import java.io.PrintWriter;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.logging.Logger;
-
-import com.vaadin.event.Transferable;
-import com.vaadin.event.TransferableImpl;
-import com.vaadin.event.dd.DragAndDropEvent;
-import com.vaadin.event.dd.DragSource;
-import com.vaadin.event.dd.DropHandler;
-import com.vaadin.event.dd.DropTarget;
-import com.vaadin.event.dd.TargetDetails;
-import com.vaadin.event.dd.TargetDetailsImpl;
-import com.vaadin.event.dd.acceptcriteria.AcceptCriterion;
-import com.vaadin.shared.communication.SharedState;
-import com.vaadin.shared.ui.dd.DragEventType;
-import com.vaadin.terminal.Extension;
-import com.vaadin.terminal.PaintException;
-import com.vaadin.terminal.VariableOwner;
-import com.vaadin.terminal.gwt.client.ui.dd.VDragAndDropManager;
-import com.vaadin.ui.Component;
-import com.vaadin.ui.Root;
-
-public class DragAndDropService implements VariableOwner, ClientConnector {
-
- private int lastVisitId;
-
- private boolean lastVisitAccepted = false;
-
- private DragAndDropEvent dragEvent;
-
- private final AbstractCommunicationManager manager;
-
- private AcceptCriterion acceptCriterion;
-
- public DragAndDropService(AbstractCommunicationManager manager) {
- this.manager = manager;
- }
-
- @Override
- public void changeVariables(Object source, Map<String, Object> variables) {
- Object owner = variables.get("dhowner");
-
- // Validate drop handler owner
- if (!(owner instanceof DropTarget)) {
- getLogger()
- .severe("DropHandler owner " + owner
- + " must implement DropTarget");
- return;
- }
- // owner cannot be null here
-
- DropTarget dropTarget = (DropTarget) owner;
- lastVisitId = (Integer) variables.get("visitId");
-
- // request may be dropRequest or request during drag operation (commonly
- // dragover or dragenter)
- boolean dropRequest = isDropRequest(variables);
- if (dropRequest) {
- handleDropRequest(dropTarget, variables);
- } else {
- handleDragRequest(dropTarget, variables);
- }
-
- }
-
- /**
- * Handles a drop request from the VDragAndDropManager.
- *
- * @param dropTarget
- * @param variables
- */
- private void handleDropRequest(DropTarget dropTarget,
- Map<String, Object> variables) {
- DropHandler dropHandler = (dropTarget).getDropHandler();
- if (dropHandler == null) {
- // No dropHandler returned so no drop can be performed.
- getLogger().fine(
- "DropTarget.getDropHandler() returned null for owner: "
- + dropTarget);
- return;
- }
-
- /*
- * Construct the Transferable and the DragDropDetails for the drop
- * operation based on the info passed from the client widgets (drag
- * source for Transferable, drop target for DragDropDetails).
- */
- Transferable transferable = constructTransferable(dropTarget, variables);
- TargetDetails dropData = constructDragDropDetails(dropTarget, variables);
- DragAndDropEvent dropEvent = new DragAndDropEvent(transferable,
- dropData);
- if (dropHandler.getAcceptCriterion().accept(dropEvent)) {
- dropHandler.drop(dropEvent);
- }
- }
-
- /**
- * Handles a drag/move request from the VDragAndDropManager.
- *
- * @param dropTarget
- * @param variables
- */
- private void handleDragRequest(DropTarget dropTarget,
- Map<String, Object> variables) {
- lastVisitId = (Integer) variables.get("visitId");
-
- acceptCriterion = dropTarget.getDropHandler().getAcceptCriterion();
-
- /*
- * Construct the Transferable and the DragDropDetails for the drag
- * operation based on the info passed from the client widgets (drag
- * source for Transferable, current target for DragDropDetails).
- */
- Transferable transferable = constructTransferable(dropTarget, variables);
- TargetDetails dragDropDetails = constructDragDropDetails(dropTarget,
- variables);
-
- dragEvent = new DragAndDropEvent(transferable, dragDropDetails);
-
- lastVisitAccepted = acceptCriterion.accept(dragEvent);
- }
-
- /**
- * Construct DragDropDetails based on variables from client drop target.
- * Uses DragDropDetailsTranslator if available, otherwise a default
- * DragDropDetails implementation is used.
- *
- * @param dropTarget
- * @param variables
- * @return
- */
- @SuppressWarnings("unchecked")
- private TargetDetails constructDragDropDetails(DropTarget dropTarget,
- Map<String, Object> variables) {
- Map<String, Object> rawDragDropDetails = (Map<String, Object>) variables
- .get("evt");
-
- TargetDetails dropData = dropTarget
- .translateDropTargetDetails(rawDragDropDetails);
-
- if (dropData == null) {
- // Create a default DragDropDetails with all the raw variables
- dropData = new TargetDetailsImpl(rawDragDropDetails, dropTarget);
- }
-
- return dropData;
- }
-
- private boolean isDropRequest(Map<String, Object> variables) {
- return getRequestType(variables) == DragEventType.DROP;
- }
-
- private DragEventType getRequestType(Map<String, Object> variables) {
- int type = (Integer) variables.get("type");
- return DragEventType.values()[type];
- }
-
- @SuppressWarnings("unchecked")
- private Transferable constructTransferable(DropTarget dropHandlerOwner,
- Map<String, Object> variables) {
- final Component sourceComponent = (Component) variables
- .get("component");
-
- variables = (Map<String, Object>) variables.get("tra");
-
- Transferable transferable = null;
- if (sourceComponent != null && sourceComponent instanceof DragSource) {
- transferable = ((DragSource) sourceComponent)
- .getTransferable(variables);
- }
- if (transferable == null) {
- transferable = new TransferableImpl(sourceComponent, variables);
- }
-
- return transferable;
- }
-
- @Override
- public boolean isEnabled() {
- return isConnectorEnabled();
- }
-
- @Override
- public boolean isImmediate() {
- return true;
- }
-
- void printJSONResponse(PrintWriter outWriter) throws PaintException {
- if (isDirty()) {
-
- outWriter.print(", \"dd\":");
-
- JsonPaintTarget jsonPaintTarget = new JsonPaintTarget(manager,
- outWriter, false);
- jsonPaintTarget.startTag("dd");
- jsonPaintTarget.addAttribute("visitId", lastVisitId);
- if (acceptCriterion != null) {
- jsonPaintTarget.addAttribute("accepted", lastVisitAccepted);
- acceptCriterion.paintResponse(jsonPaintTarget);
- }
- jsonPaintTarget.endTag("dd");
- jsonPaintTarget.close();
- lastVisitId = -1;
- lastVisitAccepted = false;
- acceptCriterion = null;
- dragEvent = null;
- }
- }
-
- private boolean isDirty() {
- if (lastVisitId > 0) {
- return true;
- }
- return false;
- }
-
- @Override
- public SharedState getState() {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public String getConnectorId() {
- return VDragAndDropManager.DD_SERVICE;
- }
-
- @Override
- public boolean isConnectorEnabled() {
- // Drag'n'drop can't be disabled
- return true;
- }
-
- @Override
- public List<ClientMethodInvocation> retrievePendingRpcCalls() {
- return null;
- }
-
- @Override
- public RpcManager getRpcManager(Class<?> rpcInterface) {
- // TODO Use rpc for drag'n'drop
- return null;
- }
-
- @Override
- public Class<? extends SharedState> getStateType() {
- return SharedState.class;
- }
-
- @Override
- public void requestRepaint() {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public ClientConnector getParent() {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public void requestRepaintAll() {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void setParent(ClientConnector parent) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void attach() {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void detach() {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public Collection<Extension> getExtensions() {
- // TODO Auto-generated method stub
- return Collections.emptySet();
- }
-
- @Override
- public void removeExtension(Extension extension) {
- // TODO Auto-generated method stub
- }
-
- private Logger getLogger() {
- return Logger.getLogger(DragAndDropService.class.getName());
- }
-
- @Override
- public Root getRoot() {
- return null;
- }
-}
diff --git a/src/com/vaadin/terminal/gwt/server/GAEApplicationServlet.java b/src/com/vaadin/terminal/gwt/server/GAEApplicationServlet.java
deleted file mode 100644
index cc12c9cc43..0000000000
--- a/src/com/vaadin/terminal/gwt/server/GAEApplicationServlet.java
+++ /dev/null
@@ -1,417 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.terminal.gwt.server;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.NotSerializableException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
-
-import com.google.appengine.api.datastore.Blob;
-import com.google.appengine.api.datastore.DatastoreService;
-import com.google.appengine.api.datastore.DatastoreServiceFactory;
-import com.google.appengine.api.datastore.Entity;
-import com.google.appengine.api.datastore.EntityNotFoundException;
-import com.google.appengine.api.datastore.FetchOptions.Builder;
-import com.google.appengine.api.datastore.Key;
-import com.google.appengine.api.datastore.KeyFactory;
-import com.google.appengine.api.datastore.PreparedQuery;
-import com.google.appengine.api.datastore.Query;
-import com.google.appengine.api.datastore.Query.FilterOperator;
-import com.google.appengine.api.memcache.Expiration;
-import com.google.appengine.api.memcache.MemcacheService;
-import com.google.appengine.api.memcache.MemcacheServiceFactory;
-import com.google.apphosting.api.DeadlineExceededException;
-import com.vaadin.service.ApplicationContext;
-
-/**
- * ApplicationServlet to be used when deploying to Google App Engine, in
- * web.xml:
- *
- * <pre>
- * &lt;servlet&gt;
- * &lt;servlet-name&gt;HelloWorld&lt;/servlet-name&gt;
- * &lt;servlet-class&gt;com.vaadin.terminal.gwt.server.GAEApplicationServlet&lt;/servlet-class&gt;
- * &lt;init-param&gt;
- * &lt;param-name&gt;application&lt;/param-name&gt;
- * &lt;param-value&gt;com.vaadin.demo.HelloWorld&lt;/param-value&gt;
- * &lt;/init-param&gt;
- * &lt;/servlet&gt;
- * </pre>
- *
- * Session support must be enabled in appengine-web.xml:
- *
- * <pre>
- * &lt;sessions-enabled&gt;true&lt;/sessions-enabled&gt;
- * </pre>
- *
- * Appengine datastore cleanup can be invoked by calling one of the applications
- * with an additional path "/CLEAN". This can be set up as a cron-job in
- * cron.xml (see appengine documentation for more information):
- *
- * <pre>
- * &lt;cronentries&gt;
- * &lt;cron&gt;
- * &lt;url&gt;/HelloWorld/CLEAN&lt;/url&gt;
- * &lt;description&gt;Clean up sessions&lt;/description&gt;
- * &lt;schedule&gt;every 2 hours&lt;/schedule&gt;
- * &lt;/cron&gt;
- * &lt;/cronentries&gt;
- * </pre>
- *
- * It is recommended (but not mandatory) to extract themes and widgetsets and
- * have App Engine server these statically. Extract VAADIN folder (and it's
- * contents) 'next to' the WEB-INF folder, and add the following to
- * appengine-web.xml:
- *
- * <pre>
- * &lt;static-files&gt;
- * &lt;include path=&quot;/VAADIN/**&quot; /&gt;
- * &lt;/static-files&gt;
- * </pre>
- *
- * Additional limitations:
- * <ul>
- * <li/>Do not change application state when serving an ApplicationResource.
- * <li/>Avoid changing application state in transaction handlers, unless you're
- * confident you fully understand the synchronization issues in App Engine.
- * <li/>The application remains locked while uploading - no progressbar is
- * possible.
- * </ul>
- */
-public class GAEApplicationServlet extends ApplicationServlet {
-
- // memcache mutex is MUTEX_BASE + sessio id
- private static final String MUTEX_BASE = "_vmutex";
-
- // used identify ApplicationContext in memcache and datastore
- private static final String AC_BASE = "_vac";
-
- // UIDL requests will attempt to gain access for this long before telling
- // the client to retry
- private static final int MAX_UIDL_WAIT_MILLISECONDS = 5000;
-
- // Tell client to retry after this delay.
- // Note: currently interpreting Retry-After as ms, not sec
- private static final int RETRY_AFTER_MILLISECONDS = 100;
-
- // Properties used in the datastore
- private static final String PROPERTY_EXPIRES = "expires";
- private static final String PROPERTY_DATA = "data";
-
- // path used for cleanup
- private static final String CLEANUP_PATH = "/CLEAN";
- // max entities to clean at once
- private static final int CLEANUP_LIMIT = 200;
- // appengine session kind
- private static final String APPENGINE_SESSION_KIND = "_ah_SESSION";
- // appengine session expires-parameter
- private static final String PROPERTY_APPENGINE_EXPIRES = "_expires";
-
- protected void sendDeadlineExceededNotification(
- WrappedHttpServletRequest request,
- WrappedHttpServletResponse response) throws IOException {
- criticalNotification(
- request,
- response,
- "Deadline Exceeded",
- "I'm sorry, but the operation took too long to complete. We'll try reloading to see where we're at, please take note of any unsaved data...",
- "", null);
- }
-
- protected void sendNotSerializableNotification(
- WrappedHttpServletRequest request,
- WrappedHttpServletResponse response) throws IOException {
- criticalNotification(
- request,
- response,
- "NotSerializableException",
- "I'm sorry, but there seems to be a serious problem, please contact the administrator. And please take note of any unsaved data...",
- "", getApplicationUrl(request).toString()
- + "?restartApplication");
- }
-
- protected void sendCriticalErrorNotification(
- WrappedHttpServletRequest request,
- WrappedHttpServletResponse response) throws IOException {
- criticalNotification(
- request,
- response,
- "Critical error",
- "I'm sorry, but there seems to be a serious problem, please contact the administrator. And please take note of any unsaved data...",
- "", getApplicationUrl(request).toString()
- + "?restartApplication");
- }
-
- @Override
- protected void service(HttpServletRequest unwrappedRequest,
- HttpServletResponse unwrappedResponse) throws ServletException,
- IOException {
- WrappedHttpServletRequest request = new WrappedHttpServletRequest(
- unwrappedRequest, getDeploymentConfiguration());
- WrappedHttpServletResponse response = new WrappedHttpServletResponse(
- unwrappedResponse, getDeploymentConfiguration());
-
- if (isCleanupRequest(request)) {
- cleanDatastore();
- return;
- }
-
- RequestType requestType = getRequestType(request);
-
- if (requestType == RequestType.STATIC_FILE) {
- // no locking needed, let superclass handle
- super.service(request, response);
- cleanSession(request);
- return;
- }
-
- if (requestType == RequestType.APPLICATION_RESOURCE) {
- // no locking needed, let superclass handle
- getApplicationContext(request,
- MemcacheServiceFactory.getMemcacheService());
- super.service(request, response);
- cleanSession(request);
- return;
- }
-
- final HttpSession session = request
- .getSession(requestCanCreateApplication(request, requestType));
- if (session == null) {
- handleServiceSessionExpired(request, response);
- cleanSession(request);
- return;
- }
-
- boolean locked = false;
- MemcacheService memcache = null;
- String mutex = MUTEX_BASE + session.getId();
- memcache = MemcacheServiceFactory.getMemcacheService();
- try {
- // try to get lock
- long started = new Date().getTime();
- // non-UIDL requests will try indefinitely
- while (requestType != RequestType.UIDL
- || new Date().getTime() - started < MAX_UIDL_WAIT_MILLISECONDS) {
- locked = memcache.put(mutex, 1, Expiration.byDeltaSeconds(40),
- MemcacheService.SetPolicy.ADD_ONLY_IF_NOT_PRESENT);
- if (locked) {
- break;
- }
- try {
- Thread.sleep(RETRY_AFTER_MILLISECONDS);
- } catch (InterruptedException e) {
- getLogger().finer(
- "Thread.sleep() interrupted while waiting for lock. Trying again. "
- + e);
- }
- }
-
- if (!locked) {
- // Not locked; only UIDL can get trough here unlocked: tell
- // client to retry
- response.setStatus(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
- // Note: currently interpreting Retry-After as ms, not sec
- response.setHeader("Retry-After", "" + RETRY_AFTER_MILLISECONDS);
- return;
- }
-
- // de-serialize or create application context, store in session
- ApplicationContext ctx = getApplicationContext(request, memcache);
-
- super.service(request, response);
-
- // serialize
- started = new Date().getTime();
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- ObjectOutputStream oos = new ObjectOutputStream(baos);
- oos.writeObject(ctx);
- oos.flush();
- byte[] bytes = baos.toByteArray();
-
- started = new Date().getTime();
-
- String id = AC_BASE + session.getId();
- Date expire = new Date(started
- + (session.getMaxInactiveInterval() * 1000));
- Expiration expires = Expiration.onDate(expire);
-
- memcache.put(id, bytes, expires);
-
- DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
- Entity entity = new Entity(AC_BASE, id);
- entity.setProperty(PROPERTY_EXPIRES, expire.getTime());
- entity.setProperty(PROPERTY_DATA, new Blob(bytes));
- ds.put(entity);
-
- } catch (DeadlineExceededException e) {
- getLogger().warning("DeadlineExceeded for " + session.getId());
- sendDeadlineExceededNotification(request, response);
- } catch (NotSerializableException e) {
- getLogger().log(Level.SEVERE, "Not serializable!", e);
-
- // TODO this notification is usually not shown - should we redirect
- // in some other way - can we?
- sendNotSerializableNotification(request, response);
- } catch (Exception e) {
- getLogger().log(Level.WARNING,
- "An exception occurred while servicing request.", e);
-
- sendCriticalErrorNotification(request, response);
- } finally {
- // "Next, please!"
- if (locked) {
- memcache.delete(mutex);
- }
- cleanSession(request);
- }
- }
-
- protected ApplicationContext getApplicationContext(
- HttpServletRequest request, MemcacheService memcache) {
- HttpSession session = request.getSession();
- String id = AC_BASE + session.getId();
- byte[] serializedAC = (byte[]) memcache.get(id);
- if (serializedAC == null) {
- DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
- Key key = KeyFactory.createKey(AC_BASE, id);
- Entity entity = null;
- try {
- entity = ds.get(key);
- } catch (EntityNotFoundException e) {
- // Ok, we were a bit optimistic; we'll create a new one later
- }
- if (entity != null) {
- Blob blob = (Blob) entity.getProperty(PROPERTY_DATA);
- serializedAC = blob.getBytes();
- // bring it to memcache
- memcache.put(AC_BASE + session.getId(), serializedAC,
- Expiration.byDeltaSeconds(session
- .getMaxInactiveInterval()),
- MemcacheService.SetPolicy.ADD_ONLY_IF_NOT_PRESENT);
- }
- }
- if (serializedAC != null) {
- ByteArrayInputStream bais = new ByteArrayInputStream(serializedAC);
- ObjectInputStream ois;
- try {
- ois = new ObjectInputStream(bais);
- ApplicationContext applicationContext = (ApplicationContext) ois
- .readObject();
- session.setAttribute(WebApplicationContext.class.getName(),
- applicationContext);
- } catch (IOException e) {
- getLogger().log(
- Level.WARNING,
- "Could not de-serialize ApplicationContext for "
- + session.getId()
- + " A new one will be created. ", e);
- } catch (ClassNotFoundException e) {
- getLogger().log(
- Level.WARNING,
- "Could not de-serialize ApplicationContext for "
- + session.getId()
- + " A new one will be created. ", e);
- }
- }
- // will create new context if the above did not
- return getApplicationContext(session);
-
- }
-
- private boolean isCleanupRequest(HttpServletRequest request) {
- String path = getRequestPathInfo(request);
- if (path != null && path.equals(CLEANUP_PATH)) {
- return true;
- }
- return false;
- }
-
- /**
- * Removes the ApplicationContext from the session in order to minimize the
- * data serialized to datastore and memcache.
- *
- * @param request
- */
- private void cleanSession(HttpServletRequest request) {
- HttpSession session = request.getSession(false);
- if (session != null) {
- session.removeAttribute(WebApplicationContext.class.getName());
- }
- }
-
- /**
- * This will look at the timestamp and delete expired persisted Vaadin and
- * appengine sessions from the datastore.
- *
- * TODO Possible improvements include: 1. Use transactions (requires entity
- * groups - overkill?) 2. Delete one-at-a-time, catch possible exception,
- * continue w/ next.
- */
- private void cleanDatastore() {
- long expire = new Date().getTime();
- try {
- DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
- // Vaadin stuff first
- {
- Query q = new Query(AC_BASE);
- q.setKeysOnly();
-
- q.addFilter(PROPERTY_EXPIRES,
- FilterOperator.LESS_THAN_OR_EQUAL, expire);
- PreparedQuery pq = ds.prepare(q);
- List<Entity> entities = pq.asList(Builder
- .withLimit(CLEANUP_LIMIT));
- if (entities != null) {
- getLogger().info(
- "Vaadin cleanup deleting " + entities.size()
- + " expired Vaadin sessions.");
- List<Key> keys = new ArrayList<Key>();
- for (Entity e : entities) {
- keys.add(e.getKey());
- }
- ds.delete(keys);
- }
- }
- // Also cleanup GAE sessions
- {
- Query q = new Query(APPENGINE_SESSION_KIND);
- q.setKeysOnly();
- q.addFilter(PROPERTY_APPENGINE_EXPIRES,
- FilterOperator.LESS_THAN_OR_EQUAL, expire);
- PreparedQuery pq = ds.prepare(q);
- List<Entity> entities = pq.asList(Builder
- .withLimit(CLEANUP_LIMIT));
- if (entities != null) {
- getLogger().info(
- "Vaadin cleanup deleting " + entities.size()
- + " expired appengine sessions.");
- List<Key> keys = new ArrayList<Key>();
- for (Entity e : entities) {
- keys.add(e.getKey());
- }
- ds.delete(keys);
- }
- }
- } catch (Exception e) {
- getLogger().log(Level.WARNING, "Exception while cleaning.", e);
- }
- }
-
- private static final Logger getLogger() {
- return Logger.getLogger(GAEApplicationServlet.class.getName());
- }
-}
diff --git a/src/com/vaadin/terminal/gwt/server/HttpServletRequestListener.java b/src/com/vaadin/terminal/gwt/server/HttpServletRequestListener.java
deleted file mode 100644
index d811cadf86..0000000000
--- a/src/com/vaadin/terminal/gwt/server/HttpServletRequestListener.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.terminal.gwt.server;
-
-import java.io.Serializable;
-
-import javax.servlet.Filter;
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import com.vaadin.Application;
-import com.vaadin.service.ApplicationContext.TransactionListener;
-import com.vaadin.terminal.Terminal;
-
-/**
- * {@link Application} that implements this interface gets notified of request
- * start and end by terminal.
- * <p>
- * Interface can be used for several helper tasks including:
- * <ul>
- * <li>Opening and closing database connections
- * <li>Implementing {@link ThreadLocal}
- * <li>Setting/Getting {@link Cookie}
- * </ul>
- * <p>
- * Alternatives for implementing similar features are are Servlet {@link Filter}
- * s and {@link TransactionListener}s in Vaadin.
- *
- * @since 6.2
- * @see PortletRequestListener
- */
-public interface HttpServletRequestListener extends Serializable {
-
- /**
- * This method is called before {@link Terminal} applies the request to
- * Application.
- *
- * @param request
- * @param response
- */
- public void onRequestStart(HttpServletRequest request,
- HttpServletResponse response);
-
- /**
- * This method is called at the end of each request.
- *
- * @param request
- * @param response
- */
- public void onRequestEnd(HttpServletRequest request,
- HttpServletResponse response);
-} \ No newline at end of file
diff --git a/src/com/vaadin/terminal/gwt/server/JsonCodec.java b/src/com/vaadin/terminal/gwt/server/JsonCodec.java
deleted file mode 100644
index 8199bc6ada..0000000000
--- a/src/com/vaadin/terminal/gwt/server/JsonCodec.java
+++ /dev/null
@@ -1,792 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal.gwt.server;
-
-import java.beans.IntrospectionException;
-import java.beans.Introspector;
-import java.beans.PropertyDescriptor;
-import java.io.Serializable;
-import java.lang.reflect.Array;
-import java.lang.reflect.GenericArrayType;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.lang.reflect.WildcardType;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-
-import com.vaadin.external.json.JSONArray;
-import com.vaadin.external.json.JSONException;
-import com.vaadin.external.json.JSONObject;
-import com.vaadin.shared.Connector;
-import com.vaadin.shared.communication.UidlValue;
-import com.vaadin.terminal.gwt.client.communication.JsonEncoder;
-import com.vaadin.ui.Component;
-import com.vaadin.ui.ConnectorTracker;
-
-/**
- * Decoder for converting RPC parameters and other values from JSON in transfer
- * between the client and the server and vice versa.
- *
- * @since 7.0
- */
-public class JsonCodec implements Serializable {
-
- private static Map<Class<?>, String> typeToTransportType = new HashMap<Class<?>, String>();
-
- /**
- * Note! This does not contain primitives.
- * <p>
- */
- private static Map<String, Class<?>> transportTypeToType = new HashMap<String, Class<?>>();
-
- static {
- registerType(String.class, JsonEncoder.VTYPE_STRING);
- registerType(Connector.class, JsonEncoder.VTYPE_CONNECTOR);
- registerType(Boolean.class, JsonEncoder.VTYPE_BOOLEAN);
- registerType(boolean.class, JsonEncoder.VTYPE_BOOLEAN);
- registerType(Integer.class, JsonEncoder.VTYPE_INTEGER);
- registerType(int.class, JsonEncoder.VTYPE_INTEGER);
- registerType(Float.class, JsonEncoder.VTYPE_FLOAT);
- registerType(float.class, JsonEncoder.VTYPE_FLOAT);
- registerType(Double.class, JsonEncoder.VTYPE_DOUBLE);
- registerType(double.class, JsonEncoder.VTYPE_DOUBLE);
- registerType(Long.class, JsonEncoder.VTYPE_LONG);
- registerType(long.class, JsonEncoder.VTYPE_LONG);
- registerType(String[].class, JsonEncoder.VTYPE_STRINGARRAY);
- registerType(Object[].class, JsonEncoder.VTYPE_ARRAY);
- registerType(Map.class, JsonEncoder.VTYPE_MAP);
- registerType(HashMap.class, JsonEncoder.VTYPE_MAP);
- registerType(List.class, JsonEncoder.VTYPE_LIST);
- registerType(Set.class, JsonEncoder.VTYPE_SET);
- }
-
- private static void registerType(Class<?> type, String transportType) {
- typeToTransportType.put(type, transportType);
- if (!type.isPrimitive()) {
- transportTypeToType.put(transportType, type);
- }
- }
-
- public static boolean isInternalTransportType(String transportType) {
- return transportTypeToType.containsKey(transportType);
- }
-
- public static boolean isInternalType(Type type) {
- if (type instanceof Class && ((Class<?>) type).isPrimitive()) {
- if (type == byte.class || type == char.class) {
- // Almost all primitive types are handled internally
- return false;
- }
- // All primitive types are handled internally
- return true;
- } else if (type == UidlValue.class) {
- // UidlValue is a special internal type wrapping type info and a
- // value
- return true;
- }
- return typeToTransportType.containsKey(getClassForType(type));
- }
-
- private static Class<?> getClassForType(Type type) {
- if (type instanceof ParameterizedType) {
- return (Class<?>) (((ParameterizedType) type).getRawType());
- } else if (type instanceof Class<?>) {
- return (Class<?>) type;
- } else {
- return null;
- }
- }
-
- private static Class<?> getType(String transportType) {
- return transportTypeToType.get(transportType);
- }
-
- public static Object decodeInternalOrCustomType(Type targetType,
- Object value, ConnectorTracker connectorTracker)
- throws JSONException {
- if (isInternalType(targetType)) {
- return decodeInternalType(targetType, false, value,
- connectorTracker);
- } else {
- return decodeCustomType(targetType, value, connectorTracker);
- }
- }
-
- public static Object decodeCustomType(Type targetType, Object value,
- ConnectorTracker connectorTracker) throws JSONException {
- if (isInternalType(targetType)) {
- throw new JSONException("decodeCustomType cannot be used for "
- + targetType + ", which is an internal type");
- }
-
- // Try to decode object using fields
- if (value == JSONObject.NULL) {
- return null;
- } else if (targetType == byte.class || targetType == Byte.class) {
- return Byte.valueOf(String.valueOf(value));
- } else if (targetType == char.class || targetType == Character.class) {
- return Character.valueOf(String.valueOf(value).charAt(0));
- } else if (targetType instanceof Class<?>
- && ((Class<?>) targetType).isArray()) {
- // Legacy Object[] and String[] handled elsewhere, this takes care
- // of generic arrays
- Class<?> componentType = ((Class<?>) targetType).getComponentType();
- return decodeArray(componentType, (JSONArray) value,
- connectorTracker);
- } else if (targetType instanceof GenericArrayType) {
- Type componentType = ((GenericArrayType) targetType)
- .getGenericComponentType();
- return decodeArray(componentType, (JSONArray) value,
- connectorTracker);
- } else if (targetType == JSONObject.class
- || targetType == JSONArray.class) {
- return value;
- } else {
- return decodeObject(targetType, (JSONObject) value,
- connectorTracker);
- }
- }
-
- private static Object decodeArray(Type componentType, JSONArray value,
- ConnectorTracker connectorTracker) throws JSONException {
- Class<?> componentClass = getClassForType(componentType);
- Object array = Array.newInstance(componentClass, value.length());
- for (int i = 0; i < value.length(); i++) {
- Object decodedValue = decodeInternalOrCustomType(componentType,
- value.get(i), connectorTracker);
- Array.set(array, i, decodedValue);
- }
- return array;
- }
-
- /**
- * Decodes a value that is of an internal type.
- * <p>
- * Ensures the encoded value is of the same type as target type.
- * </p>
- * <p>
- * Allows restricting collections so that they must be declared using
- * generics. If this is used then all objects in the collection are encoded
- * using the declared type. Otherwise only internal types are allowed in
- * collections.
- * </p>
- *
- * @param targetType
- * The type that should be returned by this method
- * @param valueAndType
- * The encoded value and type array
- * @param application
- * A reference to the application
- * @param enforceGenericsInCollections
- * true if generics should be enforce, false to only allow
- * internal types in collections
- * @return
- * @throws JSONException
- */
- public static Object decodeInternalType(Type targetType,
- boolean restrictToInternalTypes, Object encodedJsonValue,
- ConnectorTracker connectorTracker) throws JSONException {
- if (!isInternalType(targetType)) {
- throw new JSONException("Type " + targetType
- + " is not a supported internal type.");
- }
- String transportType = getInternalTransportType(targetType);
-
- if (encodedJsonValue == JSONObject.NULL) {
- return null;
- }
-
- // UidlValue
- if (targetType == UidlValue.class) {
- return decodeUidlValue((JSONArray) encodedJsonValue,
- connectorTracker);
- }
-
- // Collections
- if (JsonEncoder.VTYPE_LIST.equals(transportType)) {
- return decodeList(targetType, restrictToInternalTypes,
- (JSONArray) encodedJsonValue, connectorTracker);
- } else if (JsonEncoder.VTYPE_SET.equals(transportType)) {
- return decodeSet(targetType, restrictToInternalTypes,
- (JSONArray) encodedJsonValue, connectorTracker);
- } else if (JsonEncoder.VTYPE_MAP.equals(transportType)) {
- return decodeMap(targetType, restrictToInternalTypes,
- encodedJsonValue, connectorTracker);
- }
-
- // Arrays
- if (JsonEncoder.VTYPE_ARRAY.equals(transportType)) {
-
- return decodeObjectArray(targetType, (JSONArray) encodedJsonValue,
- connectorTracker);
-
- } else if (JsonEncoder.VTYPE_STRINGARRAY.equals(transportType)) {
- return decodeStringArray((JSONArray) encodedJsonValue);
- }
-
- // Special Vaadin types
-
- String stringValue = String.valueOf(encodedJsonValue);
-
- if (JsonEncoder.VTYPE_CONNECTOR.equals(transportType)) {
- return connectorTracker.getConnector(stringValue);
- }
-
- // Legacy types
-
- if (JsonEncoder.VTYPE_STRING.equals(transportType)) {
- return stringValue;
- } else if (JsonEncoder.VTYPE_INTEGER.equals(transportType)) {
- return Integer.valueOf(stringValue);
- } else if (JsonEncoder.VTYPE_LONG.equals(transportType)) {
- return Long.valueOf(stringValue);
- } else if (JsonEncoder.VTYPE_FLOAT.equals(transportType)) {
- return Float.valueOf(stringValue);
- } else if (JsonEncoder.VTYPE_DOUBLE.equals(transportType)) {
- return Double.valueOf(stringValue);
- } else if (JsonEncoder.VTYPE_BOOLEAN.equals(transportType)) {
- return Boolean.valueOf(stringValue);
- }
-
- throw new JSONException("Unknown type " + transportType);
- }
-
- private static UidlValue decodeUidlValue(JSONArray encodedJsonValue,
- ConnectorTracker connectorTracker) throws JSONException {
- String type = encodedJsonValue.getString(0);
-
- Object decodedValue = decodeInternalType(getType(type), true,
- encodedJsonValue.get(1), connectorTracker);
- return new UidlValue(decodedValue);
- }
-
- private static boolean transportTypesCompatible(
- String encodedTransportType, String transportType) {
- if (encodedTransportType == null) {
- return false;
- }
- if (encodedTransportType.equals(transportType)) {
- return true;
- }
- if (encodedTransportType.equals(JsonEncoder.VTYPE_NULL)) {
- return true;
- }
-
- return false;
- }
-
- private static Map<Object, Object> decodeMap(Type targetType,
- boolean restrictToInternalTypes, Object jsonMap,
- ConnectorTracker connectorTracker) throws JSONException {
- if (jsonMap instanceof JSONArray) {
- // Client-side has no declared type information to determine
- // encoding method for empty maps, so these are handled separately.
- // See #8906.
- JSONArray jsonArray = (JSONArray) jsonMap;
- if (jsonArray.length() == 0) {
- return new HashMap<Object, Object>();
- }
- }
-
- if (!restrictToInternalTypes && targetType instanceof ParameterizedType) {
- Type keyType = ((ParameterizedType) targetType)
- .getActualTypeArguments()[0];
- Type valueType = ((ParameterizedType) targetType)
- .getActualTypeArguments()[1];
- if (keyType == String.class) {
- return decodeStringMap(valueType, (JSONObject) jsonMap,
- connectorTracker);
- } else if (keyType == Connector.class) {
- return decodeConnectorMap(valueType, (JSONObject) jsonMap,
- connectorTracker);
- } else {
- return decodeObjectMap(keyType, valueType, (JSONArray) jsonMap,
- connectorTracker);
- }
- } else {
- return decodeStringMap(UidlValue.class, (JSONObject) jsonMap,
- connectorTracker);
- }
- }
-
- private static Map<Object, Object> decodeObjectMap(Type keyType,
- Type valueType, JSONArray jsonMap, ConnectorTracker connectorTracker)
- throws JSONException {
- Map<Object, Object> map = new HashMap<Object, Object>();
-
- JSONArray keys = jsonMap.getJSONArray(0);
- JSONArray values = jsonMap.getJSONArray(1);
-
- assert (keys.length() == values.length());
-
- for (int i = 0; i < keys.length(); i++) {
- Object key = decodeInternalOrCustomType(keyType, keys.get(i),
- connectorTracker);
- Object value = decodeInternalOrCustomType(valueType, values.get(i),
- connectorTracker);
-
- map.put(key, value);
- }
-
- return map;
- }
-
- private static Map<Object, Object> decodeConnectorMap(Type valueType,
- JSONObject jsonMap, ConnectorTracker connectorTracker)
- throws JSONException {
- Map<Object, Object> map = new HashMap<Object, Object>();
-
- for (Iterator<?> iter = jsonMap.keys(); iter.hasNext();) {
- String key = (String) iter.next();
- Object value = decodeInternalOrCustomType(valueType,
- jsonMap.get(key), connectorTracker);
- if (valueType == UidlValue.class) {
- value = ((UidlValue) value).getValue();
- }
- map.put(connectorTracker.getConnector(key), value);
- }
-
- return map;
- }
-
- private static Map<Object, Object> decodeStringMap(Type valueType,
- JSONObject jsonMap, ConnectorTracker connectorTracker)
- throws JSONException {
- Map<Object, Object> map = new HashMap<Object, Object>();
-
- for (Iterator<?> iter = jsonMap.keys(); iter.hasNext();) {
- String key = (String) iter.next();
- Object value = decodeInternalOrCustomType(valueType,
- jsonMap.get(key), connectorTracker);
- if (valueType == UidlValue.class) {
- value = ((UidlValue) value).getValue();
- }
- map.put(key, value);
- }
-
- return map;
- }
-
- /**
- * @param targetType
- * @param restrictToInternalTypes
- * @param typeIndex
- * The index of a generic type to use to define the child type
- * that should be decoded
- * @param encodedValueAndType
- * @param application
- * @return
- * @throws JSONException
- */
- private static Object decodeParametrizedType(Type targetType,
- boolean restrictToInternalTypes, int typeIndex, Object value,
- ConnectorTracker connectorTracker) throws JSONException {
- if (!restrictToInternalTypes && targetType instanceof ParameterizedType) {
- Type childType = ((ParameterizedType) targetType)
- .getActualTypeArguments()[typeIndex];
- // Only decode the given type
- return decodeInternalOrCustomType(childType, value,
- connectorTracker);
- } else {
- // Only UidlValue when not enforcing a given type to avoid security
- // issues
- UidlValue decodeInternalType = (UidlValue) decodeInternalType(
- UidlValue.class, true, value, connectorTracker);
- return decodeInternalType.getValue();
- }
- }
-
- private static Object decodeEnum(Class<? extends Enum> cls, JSONObject value) {
- String enumIdentifier = String.valueOf(value);
- return Enum.valueOf(cls, enumIdentifier);
- }
-
- private static String[] decodeStringArray(JSONArray jsonArray)
- throws JSONException {
- int length = jsonArray.length();
- List<String> tokens = new ArrayList<String>(length);
- for (int i = 0; i < length; ++i) {
- tokens.add(jsonArray.getString(i));
- }
- return tokens.toArray(new String[tokens.size()]);
- }
-
- private static Object[] decodeObjectArray(Type targetType,
- JSONArray jsonArray, ConnectorTracker connectorTracker)
- throws JSONException {
- List list = decodeList(List.class, true, jsonArray, connectorTracker);
- return list.toArray(new Object[list.size()]);
- }
-
- private static List<Object> decodeList(Type targetType,
- boolean restrictToInternalTypes, JSONArray jsonArray,
- ConnectorTracker connectorTracker) throws JSONException {
- List<Object> list = new ArrayList<Object>();
- for (int i = 0; i < jsonArray.length(); ++i) {
- // each entry always has two elements: type and value
- Object encodedValue = jsonArray.get(i);
- Object decodedChild = decodeParametrizedType(targetType,
- restrictToInternalTypes, 0, encodedValue, connectorTracker);
- list.add(decodedChild);
- }
- return list;
- }
-
- private static Set<Object> decodeSet(Type targetType,
- boolean restrictToInternalTypes, JSONArray jsonArray,
- ConnectorTracker connectorTracker) throws JSONException {
- HashSet<Object> set = new HashSet<Object>();
- set.addAll(decodeList(targetType, restrictToInternalTypes, jsonArray,
- connectorTracker));
- return set;
- }
-
- /**
- * Returns the name that should be used as field name in the JSON. We strip
- * "set" from the setter, keeping the result - this is easy to do on both
- * server and client, avoiding some issues with cASE. E.g setZIndex()
- * becomes "zIndex". Also ensures that both getter and setter are present,
- * returning null otherwise.
- *
- * @param pd
- * @return the name to be used or null if both getter and setter are not
- * found.
- */
- static String getTransportFieldName(PropertyDescriptor pd) {
- if (pd.getReadMethod() == null || pd.getWriteMethod() == null) {
- return null;
- }
- String fieldName = pd.getWriteMethod().getName().substring(3);
- fieldName = Character.toLowerCase(fieldName.charAt(0))
- + fieldName.substring(1);
- return fieldName;
- }
-
- private static Object decodeObject(Type targetType,
- JSONObject serializedObject, ConnectorTracker connectorTracker)
- throws JSONException {
-
- Class<?> targetClass = getClassForType(targetType);
- if (Enum.class.isAssignableFrom(targetClass)) {
- return decodeEnum(targetClass.asSubclass(Enum.class),
- serializedObject);
- }
-
- try {
- Object decodedObject = targetClass.newInstance();
- for (PropertyDescriptor pd : Introspector.getBeanInfo(targetClass)
- .getPropertyDescriptors()) {
-
- String fieldName = getTransportFieldName(pd);
- if (fieldName == null) {
- continue;
- }
- Object encodedFieldValue = serializedObject.get(fieldName);
- Type fieldType = pd.getReadMethod().getGenericReturnType();
- Object decodedFieldValue = decodeInternalOrCustomType(
- fieldType, encodedFieldValue, connectorTracker);
-
- pd.getWriteMethod().invoke(decodedObject, decodedFieldValue);
- }
-
- return decodedObject;
- } catch (IllegalArgumentException e) {
- throw new JSONException(e);
- } catch (IllegalAccessException e) {
- throw new JSONException(e);
- } catch (InvocationTargetException e) {
- throw new JSONException(e);
- } catch (InstantiationException e) {
- throw new JSONException(e);
- } catch (IntrospectionException e) {
- throw new JSONException(e);
- }
- }
-
- public static Object encode(Object value, Object referenceValue,
- Type valueType, ConnectorTracker connectorTracker)
- throws JSONException {
-
- if (valueType == null) {
- throw new IllegalArgumentException("type must be defined");
- }
-
- if (valueType instanceof WildcardType) {
- throw new IllegalStateException(
- "Can not serialize type with wildcard: " + valueType);
- }
-
- if (null == value) {
- return encodeNull();
- }
-
- if (value instanceof String[]) {
- String[] array = (String[]) value;
- JSONArray jsonArray = new JSONArray();
- for (int i = 0; i < array.length; ++i) {
- jsonArray.put(array[i]);
- }
- return jsonArray;
- } else if (value instanceof String) {
- return value;
- } else if (value instanceof Boolean) {
- return value;
- } else if (value instanceof Number) {
- return value;
- } else if (value instanceof Character) {
- // Character is not a Number
- return value;
- } else if (value instanceof Collection) {
- Collection<?> collection = (Collection<?>) value;
- JSONArray jsonArray = encodeCollection(valueType, collection,
- connectorTracker);
- return jsonArray;
- } else if (valueType instanceof Class<?>
- && ((Class<?>) valueType).isArray()) {
- JSONArray jsonArray = encodeArrayContents(
- ((Class<?>) valueType).getComponentType(), value,
- connectorTracker);
- return jsonArray;
- } else if (valueType instanceof GenericArrayType) {
- Type componentType = ((GenericArrayType) valueType)
- .getGenericComponentType();
- JSONArray jsonArray = encodeArrayContents(componentType, value,
- connectorTracker);
- return jsonArray;
- } else if (value instanceof Map) {
- Object jsonMap = encodeMap(valueType, (Map<?, ?>) value,
- connectorTracker);
- return jsonMap;
- } else if (value instanceof Connector) {
- Connector connector = (Connector) value;
- if (value instanceof Component
- && !(AbstractCommunicationManager
- .isVisible((Component) value))) {
- return encodeNull();
- }
- return connector.getConnectorId();
- } else if (value instanceof Enum) {
- return encodeEnum((Enum<?>) value, connectorTracker);
- } else if (value instanceof JSONArray || value instanceof JSONObject) {
- return value;
- } else {
- // Any object that we do not know how to encode we encode by looping
- // through fields
- return encodeObject(value, referenceValue, connectorTracker);
- }
- }
-
- private static Object encodeNull() {
- return JSONObject.NULL;
- }
-
- private static Object encodeObject(Object value, Object referenceValue,
- ConnectorTracker connectorTracker) throws JSONException {
- JSONObject jsonMap = new JSONObject();
-
- try {
- for (PropertyDescriptor pd : Introspector.getBeanInfo(
- value.getClass()).getPropertyDescriptors()) {
- String fieldName = getTransportFieldName(pd);
- if (fieldName == null) {
- continue;
- }
- Method getterMethod = pd.getReadMethod();
- // We can't use PropertyDescriptor.getPropertyType() as it does
- // not support generics
- Type fieldType = getterMethod.getGenericReturnType();
- Object fieldValue = getterMethod.invoke(value, (Object[]) null);
- boolean equals = false;
- Object referenceFieldValue = null;
- if (referenceValue != null) {
- referenceFieldValue = getterMethod.invoke(referenceValue,
- (Object[]) null);
- equals = equals(fieldValue, referenceFieldValue);
- }
- if (!equals) {
- if (jsonMap.has(fieldName)) {
- throw new RuntimeException(
- "Can't encode "
- + value.getClass().getName()
- + " as it has multiple fields with the name "
- + fieldName.toLowerCase()
- + ". This can happen if only casing distinguishes one property name from another.");
- }
- jsonMap.put(
- fieldName,
- encode(fieldValue, referenceFieldValue, fieldType,
- connectorTracker));
- // } else {
- // System.out.println("Skipping field " + fieldName
- // + " of type " + fieldType.getName()
- // + " for object " + value.getClass().getName()
- // + " as " + fieldValue + "==" + referenceFieldValue);
- }
- }
- } catch (Exception e) {
- // TODO: Should exceptions be handled in a different way?
- throw new JSONException(e);
- }
- return jsonMap;
- }
-
- /**
- * Compares the value with the reference. If they match, returns true.
- *
- * @param fieldValue
- * @param referenceValue
- * @return
- */
- private static boolean equals(Object fieldValue, Object referenceValue) {
- if (fieldValue == null) {
- return referenceValue == null;
- }
-
- if (fieldValue.equals(referenceValue)) {
- return true;
- }
-
- return false;
- }
-
- private static String encodeEnum(Enum<?> e,
- ConnectorTracker connectorTracker) throws JSONException {
- return e.name();
- }
-
- private static JSONArray encodeArrayContents(Type componentType,
- Object array, ConnectorTracker connectorTracker)
- throws JSONException {
- JSONArray jsonArray = new JSONArray();
- for (int i = 0; i < Array.getLength(array); i++) {
- jsonArray.put(encode(Array.get(array, i), null, componentType,
- connectorTracker));
- }
- return jsonArray;
- }
-
- private static JSONArray encodeCollection(Type targetType,
- Collection collection, ConnectorTracker connectorTracker)
- throws JSONException {
- JSONArray jsonArray = new JSONArray();
- for (Object o : collection) {
- jsonArray.put(encodeChild(targetType, 0, o, connectorTracker));
- }
- return jsonArray;
- }
-
- private static Object encodeChild(Type targetType, int typeIndex, Object o,
- ConnectorTracker connectorTracker) throws JSONException {
- if (targetType instanceof ParameterizedType) {
- Type childType = ((ParameterizedType) targetType)
- .getActualTypeArguments()[typeIndex];
- // Encode using the given type
- return encode(o, null, childType, connectorTracker);
- } else {
- throw new JSONException("Collection is missing generics");
- }
- }
-
- private static Object encodeMap(Type mapType, Map<?, ?> map,
- ConnectorTracker connectorTracker) throws JSONException {
- Type keyType, valueType;
-
- if (mapType instanceof ParameterizedType) {
- keyType = ((ParameterizedType) mapType).getActualTypeArguments()[0];
- valueType = ((ParameterizedType) mapType).getActualTypeArguments()[1];
- } else {
- throw new JSONException("Map is missing generics");
- }
-
- if (map.isEmpty()) {
- // Client -> server encodes empty map as an empty array because of
- // #8906. Do the same for server -> client to maintain symmetry.
- return new JSONArray();
- }
-
- if (keyType == String.class) {
- return encodeStringMap(valueType, map, connectorTracker);
- } else if (keyType == Connector.class) {
- return encodeConnectorMap(valueType, map, connectorTracker);
- } else {
- return encodeObjectMap(keyType, valueType, map, connectorTracker);
- }
- }
-
- private static JSONArray encodeObjectMap(Type keyType, Type valueType,
- Map<?, ?> map, ConnectorTracker connectorTracker)
- throws JSONException {
- JSONArray keys = new JSONArray();
- JSONArray values = new JSONArray();
-
- for (Entry<?, ?> entry : map.entrySet()) {
- Object encodedKey = encode(entry.getKey(), null, keyType,
- connectorTracker);
- Object encodedValue = encode(entry.getValue(), null, valueType,
- connectorTracker);
-
- keys.put(encodedKey);
- values.put(encodedValue);
- }
-
- return new JSONArray(Arrays.asList(keys, values));
- }
-
- private static JSONObject encodeConnectorMap(Type valueType, Map<?, ?> map,
- ConnectorTracker connectorTracker) throws JSONException {
- JSONObject jsonMap = new JSONObject();
-
- for (Entry<?, ?> entry : map.entrySet()) {
- Connector key = (Connector) entry.getKey();
- Object encodedValue = encode(entry.getValue(), null, valueType,
- connectorTracker);
- jsonMap.put(key.getConnectorId(), encodedValue);
- }
-
- return jsonMap;
- }
-
- private static JSONObject encodeStringMap(Type valueType, Map<?, ?> map,
- ConnectorTracker connectorTracker) throws JSONException {
- JSONObject jsonMap = new JSONObject();
-
- for (Entry<?, ?> entry : map.entrySet()) {
- String key = (String) entry.getKey();
- Object encodedValue = encode(entry.getValue(), null, valueType,
- connectorTracker);
- jsonMap.put(key, encodedValue);
- }
-
- return jsonMap;
- }
-
- /**
- * Gets the transport type for the given class. Returns null if no transport
- * type can be found.
- *
- * @param valueType
- * The type that should be transported
- * @return
- * @throws JSONException
- */
- private static String getInternalTransportType(Type valueType) {
- return typeToTransportType.get(getClassForType(valueType));
- }
-
- private static String getCustomTransportType(Class<?> targetType) {
- return targetType.getName();
- }
-
-}
diff --git a/src/com/vaadin/terminal/gwt/server/JsonPaintTarget.java b/src/com/vaadin/terminal/gwt/server/JsonPaintTarget.java
deleted file mode 100644
index 5a830ddb63..0000000000
--- a/src/com/vaadin/terminal/gwt/server/JsonPaintTarget.java
+++ /dev/null
@@ -1,1022 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal.gwt.server;
-
-import java.io.PrintWriter;
-import java.io.Serializable;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-import java.util.Stack;
-import java.util.Vector;
-import java.util.logging.Logger;
-
-import com.vaadin.terminal.PaintException;
-import com.vaadin.terminal.PaintTarget;
-import com.vaadin.terminal.Resource;
-import com.vaadin.terminal.StreamVariable;
-import com.vaadin.terminal.VariableOwner;
-import com.vaadin.ui.Alignment;
-import com.vaadin.ui.Component;
-import com.vaadin.ui.CustomLayout;
-
-/**
- * User Interface Description Language Target.
- *
- * TODO document better: role of this class, UIDL format, attributes, variables,
- * etc.
- *
- * @author Vaadin Ltd.
- * @version
- * @VERSION@
- * @since 5.0
- */
-@SuppressWarnings("serial")
-public class JsonPaintTarget implements PaintTarget {
-
- /* Document type declarations */
-
- private final static String UIDL_ARG_NAME = "name";
-
- private final Stack<String> mOpenTags;
-
- private final Stack<JsonTag> openJsonTags;
-
- // these match each other element-wise
- private final Stack<ClientConnector> openPaintables;
- private final Stack<String> openPaintableTags;
-
- private final PrintWriter uidlBuffer;
-
- private boolean closed = false;
-
- private final AbstractCommunicationManager manager;
-
- private int changes = 0;
-
- private final Set<Object> usedResources = new HashSet<Object>();
-
- private boolean customLayoutArgumentsOpen = false;
-
- private JsonTag tag;
-
- private boolean cacheEnabled = false;
-
- private final Set<Class<? extends ClientConnector>> usedClientConnectors = new HashSet<Class<? extends ClientConnector>>();
-
- /**
- * Creates a new JsonPaintTarget.
- *
- * @param manager
- * @param outWriter
- * A character-output stream.
- * @param cachingRequired
- * true if this is not a full repaint, i.e. caches are to be
- * used.
- * @throws PaintException
- * if the paint operation failed.
- */
- public JsonPaintTarget(AbstractCommunicationManager manager,
- PrintWriter outWriter, boolean cachingRequired)
- throws PaintException {
-
- this.manager = manager;
-
- // Sets the target for UIDL writing
- uidlBuffer = outWriter;
-
- // Initialize tag-writing
- mOpenTags = new Stack<String>();
- openJsonTags = new Stack<JsonTag>();
-
- openPaintables = new Stack<ClientConnector>();
- openPaintableTags = new Stack<String>();
-
- cacheEnabled = cachingRequired;
- }
-
- @Override
- public void startTag(String tagName) throws PaintException {
- startTag(tagName, false);
- }
-
- /**
- * Prints the element start tag.
- *
- * <pre>
- * Todo:
- * Checking of input values
- *
- * </pre>
- *
- * @param tagName
- * the name of the start tag.
- * @throws PaintException
- * if the paint operation failed.
- *
- */
- public void startTag(String tagName, boolean isChildNode)
- throws PaintException {
- // In case of null data output nothing:
- if (tagName == null) {
- throw new NullPointerException();
- }
-
- // Ensures that the target is open
- if (closed) {
- throw new PaintException(
- "Attempted to write to a closed PaintTarget.");
- }
-
- if (tag != null) {
- openJsonTags.push(tag);
- }
- // Checks tagName and attributes here
- mOpenTags.push(tagName);
-
- tag = new JsonTag(tagName);
-
- customLayoutArgumentsOpen = false;
-
- }
-
- /**
- * Prints the element end tag.
- *
- * If the parent tag is closed before every child tag is closed an
- * PaintException is raised.
- *
- * @param tag
- * the name of the end tag.
- * @throws Paintexception
- * if the paint operation failed.
- */
-
- @Override
- public void endTag(String tagName) throws PaintException {
- // In case of null data output nothing:
- if (tagName == null) {
- throw new NullPointerException();
- }
-
- // Ensure that the target is open
- if (closed) {
- throw new PaintException(
- "Attempted to write to a closed PaintTarget.");
- }
-
- if (openJsonTags.size() > 0) {
- final JsonTag parent = openJsonTags.pop();
-
- String lastTag = "";
-
- lastTag = mOpenTags.pop();
- if (!tagName.equalsIgnoreCase(lastTag)) {
- throw new PaintException("Invalid UIDL: wrong ending tag: '"
- + tagName + "' expected: '" + lastTag + "'.");
- }
-
- parent.addData(tag.getJSON());
-
- tag = parent;
- } else {
- changes++;
- uidlBuffer.print(((changes > 1) ? "," : "") + tag.getJSON());
- tag = null;
- }
- }
-
- /**
- * Substitutes the XML sensitive characters with predefined XML entities.
- *
- * @param xml
- * the String to be substituted.
- * @return A new string instance where all occurrences of XML sensitive
- * characters are substituted with entities.
- */
- static public String escapeXML(String xml) {
- if (xml == null || xml.length() <= 0) {
- return "";
- }
- return escapeXML(new StringBuilder(xml)).toString();
- }
-
- /**
- * Substitutes the XML sensitive characters with predefined XML entities.
- *
- * @param xml
- * the String to be substituted.
- * @return A new StringBuilder instance where all occurrences of XML
- * sensitive characters are substituted with entities.
- *
- */
- static StringBuilder escapeXML(StringBuilder xml) {
- if (xml == null || xml.length() <= 0) {
- return new StringBuilder("");
- }
-
- final StringBuilder result = new StringBuilder(xml.length() * 2);
-
- for (int i = 0; i < xml.length(); i++) {
- final char c = xml.charAt(i);
- final String s = toXmlChar(c);
- if (s != null) {
- result.append(s);
- } else {
- result.append(c);
- }
- }
- return result;
- }
-
- /**
- * Escapes the given string so it can safely be used as a JSON string.
- *
- * @param s
- * The string to escape
- * @return Escaped version of the string
- */
- static public String escapeJSON(String s) {
- // FIXME: Move this method to another class as other classes use it
- // also.
- if (s == null) {
- return "";
- }
- final StringBuilder sb = new StringBuilder();
- for (int i = 0; i < s.length(); i++) {
- final char ch = s.charAt(i);
- switch (ch) {
- case '"':
- sb.append("\\\"");
- break;
- case '\\':
- sb.append("\\\\");
- break;
- case '\b':
- sb.append("\\b");
- break;
- case '\f':
- sb.append("\\f");
- break;
- case '\n':
- sb.append("\\n");
- break;
- case '\r':
- sb.append("\\r");
- break;
- case '\t':
- sb.append("\\t");
- break;
- case '/':
- sb.append("\\/");
- break;
- default:
- if (ch >= '\u0000' && ch <= '\u001F') {
- final String ss = Integer.toHexString(ch);
- sb.append("\\u");
- for (int k = 0; k < 4 - ss.length(); k++) {
- sb.append('0');
- }
- sb.append(ss.toUpperCase());
- } else {
- sb.append(ch);
- }
- }
- }
- return sb.toString();
- }
-
- /**
- * Substitutes a XML sensitive character with predefined XML entity.
- *
- * @param c
- * the Character to be replaced with an entity.
- * @return String of the entity or null if character is not to be replaced
- * with an entity.
- */
- private static String toXmlChar(char c) {
- switch (c) {
- case '&':
- return "&amp;"; // & => &amp;
- case '>':
- return "&gt;"; // > => &gt;
- case '<':
- return "&lt;"; // < => &lt;
- case '"':
- return "&quot;"; // " => &quot;
- case '\'':
- return "&apos;"; // ' => &apos;
- default:
- return null;
- }
- }
-
- /**
- * Prints XML-escaped text.
- *
- * @param str
- * @throws PaintException
- * if the paint operation failed.
- *
- */
-
- @Override
- public void addText(String str) throws PaintException {
- tag.addData("\"" + escapeJSON(str) + "\"");
- }
-
- @Override
- public void addAttribute(String name, boolean value) throws PaintException {
- tag.addAttribute("\"" + name + "\":" + (value ? "true" : "false"));
- }
-
- @Override
- public void addAttribute(String name, Resource value) throws PaintException {
- if (value == null) {
- throw new NullPointerException();
- }
- ResourceReference reference = ResourceReference.create(value);
- addAttribute(name, reference.getURL());
- }
-
- @Override
- public void addAttribute(String name, int value) throws PaintException {
- tag.addAttribute("\"" + name + "\":" + String.valueOf(value));
- }
-
- @Override
- public void addAttribute(String name, long value) throws PaintException {
- tag.addAttribute("\"" + name + "\":" + String.valueOf(value));
- }
-
- @Override
- public void addAttribute(String name, float value) throws PaintException {
- tag.addAttribute("\"" + name + "\":" + String.valueOf(value));
- }
-
- @Override
- public void addAttribute(String name, double value) throws PaintException {
- tag.addAttribute("\"" + name + "\":" + String.valueOf(value));
- }
-
- @Override
- public void addAttribute(String name, String value) throws PaintException {
- // In case of null data output nothing:
- if ((value == null) || (name == null)) {
- throw new NullPointerException(
- "Parameters must be non-null strings");
- }
-
- tag.addAttribute("\"" + name + "\":\"" + escapeJSON(value) + "\"");
-
- if (customLayoutArgumentsOpen && "template".equals(name)) {
- getUsedResources().add("layouts/" + value + ".html");
- }
-
- if (name.equals("locale")) {
- manager.requireLocale(value);
- }
-
- }
-
- @Override
- public void addAttribute(String name, Component value)
- throws PaintException {
- final String id = value.getConnectorId();
- addAttribute(name, id);
- }
-
- @Override
- public void addAttribute(String name, Map<?, ?> value)
- throws PaintException {
-
- StringBuilder sb = new StringBuilder();
- sb.append("\"");
- sb.append(name);
- sb.append("\":");
- sb.append("{");
- for (Iterator<?> it = value.keySet().iterator(); it.hasNext();) {
- Object key = it.next();
- Object mapValue = value.get(key);
- sb.append("\"");
- if (key instanceof ClientConnector) {
- sb.append(((ClientConnector) key).getConnectorId());
- } else {
- sb.append(escapeJSON(key.toString()));
- }
- sb.append("\":");
- if (mapValue instanceof Float || mapValue instanceof Integer
- || mapValue instanceof Double
- || mapValue instanceof Boolean
- || mapValue instanceof Alignment) {
- sb.append(mapValue);
- } else {
- sb.append("\"");
- sb.append(escapeJSON(mapValue.toString()));
- sb.append("\"");
- }
- if (it.hasNext()) {
- sb.append(",");
- }
- }
- sb.append("}");
-
- tag.addAttribute(sb.toString());
- }
-
- @Override
- public void addAttribute(String name, Object[] values) {
- // In case of null data output nothing:
- if ((values == null) || (name == null)) {
- throw new NullPointerException(
- "Parameters must be non-null strings");
- }
- final StringBuilder buf = new StringBuilder();
- buf.append("\"" + name + "\":[");
- for (int i = 0; i < values.length; i++) {
- if (i > 0) {
- buf.append(",");
- }
- buf.append("\"");
- buf.append(escapeJSON(values[i].toString()));
- buf.append("\"");
- }
- buf.append("]");
- tag.addAttribute(buf.toString());
- }
-
- @Override
- public void addVariable(VariableOwner owner, String name, String value)
- throws PaintException {
- tag.addVariable(new StringVariable(owner, name, escapeJSON(value)));
- }
-
- @Override
- public void addVariable(VariableOwner owner, String name, Component value)
- throws PaintException {
- tag.addVariable(new StringVariable(owner, name, value.getConnectorId()));
- }
-
- @Override
- public void addVariable(VariableOwner owner, String name, int value)
- throws PaintException {
- tag.addVariable(new IntVariable(owner, name, value));
- }
-
- @Override
- public void addVariable(VariableOwner owner, String name, long value)
- throws PaintException {
- tag.addVariable(new LongVariable(owner, name, value));
- }
-
- @Override
- public void addVariable(VariableOwner owner, String name, float value)
- throws PaintException {
- tag.addVariable(new FloatVariable(owner, name, value));
- }
-
- @Override
- public void addVariable(VariableOwner owner, String name, double value)
- throws PaintException {
- tag.addVariable(new DoubleVariable(owner, name, value));
- }
-
- @Override
- public void addVariable(VariableOwner owner, String name, boolean value)
- throws PaintException {
- tag.addVariable(new BooleanVariable(owner, name, value));
- }
-
- @Override
- public void addVariable(VariableOwner owner, String name, String[] value)
- throws PaintException {
- tag.addVariable(new ArrayVariable(owner, name, value));
- }
-
- /**
- * Adds a upload stream type variable.
- *
- * TODO not converted for JSON
- *
- * @param owner
- * the Listener for variable changes.
- * @param name
- * the Variable name.
- *
- * @throws PaintException
- * if the paint operation failed.
- */
-
- @Override
- public void addUploadStreamVariable(VariableOwner owner, String name)
- throws PaintException {
- startTag("uploadstream");
- addAttribute(UIDL_ARG_NAME, name);
- endTag("uploadstream");
- }
-
- /**
- * Prints the single text section.
- *
- * Prints full text section. The section data is escaped
- *
- * @param sectionTagName
- * the name of the tag.
- * @param sectionData
- * the section data to be printed.
- * @throws PaintException
- * if the paint operation failed.
- */
-
- @Override
- public void addSection(String sectionTagName, String sectionData)
- throws PaintException {
- tag.addData("{\"" + sectionTagName + "\":\"" + escapeJSON(sectionData)
- + "\"}");
- }
-
- /**
- * Adds XML directly to UIDL.
- *
- * @param xml
- * the Xml to be added.
- * @throws PaintException
- * if the paint operation failed.
- */
-
- @Override
- public void addUIDL(String xml) throws PaintException {
-
- // Ensure that the target is open
- if (closed) {
- throw new PaintException(
- "Attempted to write to a closed PaintTarget.");
- }
-
- // Make sure that the open start tag is closed before
- // anything is written.
-
- // Escape and write what was given
- if (xml != null) {
- tag.addData("\"" + escapeJSON(xml) + "\"");
- }
-
- }
-
- /**
- * Adds XML section with namespace.
- *
- * @param sectionTagName
- * the name of the tag.
- * @param sectionData
- * the section data.
- * @param namespace
- * the namespace to be added.
- * @throws PaintException
- * if the paint operation failed.
- *
- * @see com.vaadin.terminal.PaintTarget#addXMLSection(String, String,
- * String)
- */
-
- @Override
- public void addXMLSection(String sectionTagName, String sectionData,
- String namespace) throws PaintException {
-
- // Ensure that the target is open
- if (closed) {
- throw new PaintException(
- "Attempted to write to a closed PaintTarget.");
- }
-
- startTag(sectionTagName);
- if (namespace != null) {
- addAttribute("xmlns", namespace);
- }
-
- if (sectionData != null) {
- tag.addData("\"" + escapeJSON(sectionData) + "\"");
- }
- endTag(sectionTagName);
- }
-
- /**
- * Gets the UIDL already printed to stream. Paint target must be closed
- * before the <code>getUIDL</code> can be called.
- *
- * @return the UIDL.
- */
- public String getUIDL() {
- if (closed) {
- return uidlBuffer.toString();
- }
- throw new IllegalStateException(
- "Tried to read UIDL from open PaintTarget");
- }
-
- /**
- * Closes the paint target. Paint target must be closed before the
- * <code>getUIDL</code> can be called. Subsequent attempts to write to paint
- * target. If the target was already closed, call to this function is
- * ignored. will generate an exception.
- *
- * @throws PaintException
- * if the paint operation failed.
- */
- public void close() throws PaintException {
- if (tag != null) {
- uidlBuffer.write(tag.getJSON());
- }
- flush();
- closed = true;
- }
-
- /**
- * Method flush.
- */
- private void flush() {
- uidlBuffer.flush();
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.terminal.PaintTarget#startPaintable(com.vaadin.terminal
- * .Paintable, java.lang.String)
- */
-
- @Override
- public PaintStatus startPaintable(Component connector, String tagName)
- throws PaintException {
- boolean topLevelPaintable = openPaintables.isEmpty();
-
- getLogger().fine(
- "startPaintable for " + connector.getClass().getName() + "@"
- + Integer.toHexString(connector.hashCode()));
- startTag(tagName, true);
-
- openPaintables.push(connector);
- openPaintableTags.push(tagName);
-
- addAttribute("id", connector.getConnectorId());
-
- // Only paint top level paintables. All sub paintables are marked as
- // queued and painted separately later.
- if (!topLevelPaintable) {
- return PaintStatus.CACHED;
- }
-
- if (connector instanceof CustomLayout) {
- customLayoutArgumentsOpen = true;
- }
- return PaintStatus.PAINTING;
- }
-
- @Override
- public void endPaintable(Component paintable) throws PaintException {
- getLogger().fine(
- "endPaintable for " + paintable.getClass().getName() + "@"
- + Integer.toHexString(paintable.hashCode()));
-
- ClientConnector openPaintable = openPaintables.peek();
- if (paintable != openPaintable) {
- throw new PaintException("Invalid UIDL: closing wrong paintable: '"
- + paintable.getConnectorId() + "' expected: '"
- + openPaintable.getConnectorId() + "'.");
- }
- // remove paintable from the stack
- openPaintables.pop();
- String openTag = openPaintableTags.pop();
- endTag(openTag);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.terminal.PaintTarget#addCharacterData(java.lang.String )
- */
-
- @Override
- public void addCharacterData(String text) throws PaintException {
- if (text != null) {
- tag.addData(text);
- }
- }
-
- /**
- * This is basically a container for UI components variables, that will be
- * added at the end of JSON object.
- *
- * @author mattitahvonen
- *
- */
- class JsonTag implements Serializable {
- boolean firstField = false;
-
- Vector<Object> variables = new Vector<Object>();
-
- Vector<Object> children = new Vector<Object>();
-
- Vector<Object> attr = new Vector<Object>();
-
- StringBuilder data = new StringBuilder();
-
- public boolean childrenArrayOpen = false;
-
- private boolean childNode = false;
-
- private boolean tagClosed = false;
-
- public JsonTag(String tagName) {
- data.append("[\"" + tagName + "\"");
- }
-
- private void closeTag() {
- if (!tagClosed) {
- data.append(attributesAsJsonObject());
- data.append(getData());
- // Writes the end (closing) tag
- data.append("]");
- tagClosed = true;
- }
- }
-
- public String getJSON() {
- if (!tagClosed) {
- closeTag();
- }
- return data.toString();
- }
-
- public void openChildrenArray() {
- if (!childrenArrayOpen) {
- // append("c : [");
- childrenArrayOpen = true;
- // firstField = true;
- }
- }
-
- public void closeChildrenArray() {
- // append("]");
- // firstField = false;
- }
-
- public void setChildNode(boolean b) {
- childNode = b;
- }
-
- public boolean isChildNode() {
- return childNode;
- }
-
- public String startField() {
- if (firstField) {
- firstField = false;
- return "";
- } else {
- return ",";
- }
- }
-
- /**
- *
- * @param s
- * json string, object or array
- */
- public void addData(String s) {
- children.add(s);
- }
-
- public String getData() {
- final StringBuilder buf = new StringBuilder();
- final Iterator<Object> it = children.iterator();
- while (it.hasNext()) {
- buf.append(startField());
- buf.append(it.next());
- }
- return buf.toString();
- }
-
- public void addAttribute(String jsonNode) {
- attr.add(jsonNode);
- }
-
- private String attributesAsJsonObject() {
- final StringBuilder buf = new StringBuilder();
- buf.append(startField());
- buf.append("{");
- for (final Iterator<Object> iter = attr.iterator(); iter.hasNext();) {
- final String element = (String) iter.next();
- buf.append(element);
- if (iter.hasNext()) {
- buf.append(",");
- }
- }
- buf.append(tag.variablesAsJsonObject());
- buf.append("}");
- return buf.toString();
- }
-
- public void addVariable(Variable v) {
- variables.add(v);
- }
-
- private String variablesAsJsonObject() {
- if (variables.size() == 0) {
- return "";
- }
- final StringBuilder buf = new StringBuilder();
- buf.append(startField());
- buf.append("\"v\":{");
- final Iterator<Object> iter = variables.iterator();
- while (iter.hasNext()) {
- final Variable element = (Variable) iter.next();
- buf.append(element.getJsonPresentation());
- if (iter.hasNext()) {
- buf.append(",");
- }
- }
- buf.append("}");
- return buf.toString();
- }
- }
-
- abstract class Variable implements Serializable {
-
- String name;
-
- public abstract String getJsonPresentation();
- }
-
- class BooleanVariable extends Variable implements Serializable {
- boolean value;
-
- public BooleanVariable(VariableOwner owner, String name, boolean v) {
- value = v;
- this.name = name;
- }
-
- @Override
- public String getJsonPresentation() {
- return "\"" + name + "\":" + (value == true ? "true" : "false");
- }
-
- }
-
- class StringVariable extends Variable implements Serializable {
- String value;
-
- public StringVariable(VariableOwner owner, String name, String v) {
- value = v;
- this.name = name;
- }
-
- @Override
- public String getJsonPresentation() {
- return "\"" + name + "\":\"" + value + "\"";
- }
-
- }
-
- class IntVariable extends Variable implements Serializable {
- int value;
-
- public IntVariable(VariableOwner owner, String name, int v) {
- value = v;
- this.name = name;
- }
-
- @Override
- public String getJsonPresentation() {
- return "\"" + name + "\":" + value;
- }
- }
-
- class LongVariable extends Variable implements Serializable {
- long value;
-
- public LongVariable(VariableOwner owner, String name, long v) {
- value = v;
- this.name = name;
- }
-
- @Override
- public String getJsonPresentation() {
- return "\"" + name + "\":" + value;
- }
- }
-
- class FloatVariable extends Variable implements Serializable {
- float value;
-
- public FloatVariable(VariableOwner owner, String name, float v) {
- value = v;
- this.name = name;
- }
-
- @Override
- public String getJsonPresentation() {
- return "\"" + name + "\":" + value;
- }
- }
-
- class DoubleVariable extends Variable implements Serializable {
- double value;
-
- public DoubleVariable(VariableOwner owner, String name, double v) {
- value = v;
- this.name = name;
- }
-
- @Override
- public String getJsonPresentation() {
- return "\"" + name + "\":" + value;
- }
- }
-
- class ArrayVariable extends Variable implements Serializable {
- String[] value;
-
- public ArrayVariable(VariableOwner owner, String name, String[] v) {
- value = v;
- this.name = name;
- }
-
- @Override
- public String getJsonPresentation() {
- StringBuilder sb = new StringBuilder();
- sb.append("\"");
- sb.append(name);
- sb.append("\":[");
- for (int i = 0; i < value.length;) {
- sb.append("\"");
- sb.append(escapeJSON(value[i]));
- sb.append("\"");
- i++;
- if (i < value.length) {
- sb.append(",");
- }
- }
- sb.append("]");
- return sb.toString();
- }
- }
-
- public Set<Object> getUsedResources() {
- return usedResources;
- }
-
- @Override
- @SuppressWarnings("unchecked")
- public String getTag(ClientConnector clientConnector) {
- Class<? extends ClientConnector> clientConnectorClass = clientConnector
- .getClass();
- while (clientConnectorClass.isAnonymousClass()) {
- clientConnectorClass = (Class<? extends ClientConnector>) clientConnectorClass
- .getSuperclass();
- }
- Class<?> clazz = clientConnectorClass;
- while (!usedClientConnectors.contains(clazz)
- && clazz.getSuperclass() != null
- && ClientConnector.class.isAssignableFrom(clazz)) {
- usedClientConnectors.add((Class<? extends ClientConnector>) clazz);
- clazz = clazz.getSuperclass();
- }
- return manager.getTagForType(clientConnectorClass);
- }
-
- Collection<Class<? extends ClientConnector>> getUsedClientConnectors() {
- return usedClientConnectors;
- }
-
- @Override
- public void addVariable(VariableOwner owner, String name,
- StreamVariable value) throws PaintException {
- String url = manager.getStreamVariableTargetUrl(
- (ClientConnector) owner, name, value);
- if (url != null) {
- addVariable(owner, name, url);
- } // else { //NOP this was just a cleanup by component }
-
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.terminal.PaintTarget#isFullRepaint()
- */
-
- @Override
- public boolean isFullRepaint() {
- return !cacheEnabled;
- }
-
- private static final Logger getLogger() {
- return Logger.getLogger(JsonPaintTarget.class.getName());
- }
-
-}
diff --git a/src/com/vaadin/terminal/gwt/server/LegacyChangeVariablesInvocation.java b/src/com/vaadin/terminal/gwt/server/LegacyChangeVariablesInvocation.java
deleted file mode 100644
index 9dba05d2c1..0000000000
--- a/src/com/vaadin/terminal/gwt/server/LegacyChangeVariablesInvocation.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.terminal.gwt.server;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import com.vaadin.shared.communication.MethodInvocation;
-import com.vaadin.terminal.gwt.client.ApplicationConnection;
-
-public class LegacyChangeVariablesInvocation extends MethodInvocation {
- private Map<String, Object> variableChanges = new HashMap<String, Object>();
-
- public LegacyChangeVariablesInvocation(String connectorId,
- String variableName, Object value) {
- super(connectorId, ApplicationConnection.UPDATE_VARIABLE_INTERFACE,
- ApplicationConnection.UPDATE_VARIABLE_METHOD);
- setVariableChange(variableName, value);
- }
-
- public static boolean isLegacyVariableChange(String interfaceName,
- String methodName) {
- return ApplicationConnection.UPDATE_VARIABLE_METHOD
- .equals(interfaceName)
- && ApplicationConnection.UPDATE_VARIABLE_METHOD
- .equals(methodName);
- }
-
- public void setVariableChange(String name, Object value) {
- variableChanges.put(name, value);
- }
-
- public Map<String, Object> getVariableChanges() {
- return variableChanges;
- }
-
-}
diff --git a/src/com/vaadin/terminal/gwt/server/NoInputStreamException.java b/src/com/vaadin/terminal/gwt/server/NoInputStreamException.java
deleted file mode 100644
index 70c3add858..0000000000
--- a/src/com/vaadin/terminal/gwt/server/NoInputStreamException.java
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.terminal.gwt.server;
-
-@SuppressWarnings("serial")
-public class NoInputStreamException extends Exception {
-
-}
diff --git a/src/com/vaadin/terminal/gwt/server/NoOutputStreamException.java b/src/com/vaadin/terminal/gwt/server/NoOutputStreamException.java
deleted file mode 100644
index e4db8453b0..0000000000
--- a/src/com/vaadin/terminal/gwt/server/NoOutputStreamException.java
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.terminal.gwt.server;
-
-@SuppressWarnings("serial")
-public class NoOutputStreamException extends Exception {
-
-}
diff --git a/src/com/vaadin/terminal/gwt/server/PortletApplicationContext2.java b/src/com/vaadin/terminal/gwt/server/PortletApplicationContext2.java
deleted file mode 100644
index 70505ab5f9..0000000000
--- a/src/com/vaadin/terminal/gwt/server/PortletApplicationContext2.java
+++ /dev/null
@@ -1,398 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-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.StateAwareResponse;
-import javax.servlet.http.HttpSessionBindingListener;
-import javax.xml.namespace.QName;
-
-import com.vaadin.Application;
-import com.vaadin.terminal.ExternalResource;
-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 {
-
- 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>();
-
- @Override
- 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
- getLogger()
- .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;
- }
-
- /**
- * 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);
- root.getPage().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);
- root.getPage().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");
- }
- }
-
- private Logger getLogger() {
- return Logger.getLogger(PortletApplicationContext2.class.getName());
- }
-}
diff --git a/src/com/vaadin/terminal/gwt/server/PortletCommunicationManager.java b/src/com/vaadin/terminal/gwt/server/PortletCommunicationManager.java
deleted file mode 100644
index 39c27d05fe..0000000000
--- a/src/com/vaadin/terminal/gwt/server/PortletCommunicationManager.java
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.terminal.gwt.server;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-import javax.portlet.MimeResponse;
-import javax.portlet.PortletContext;
-import javax.portlet.PortletRequest;
-import javax.portlet.PortletResponse;
-import javax.portlet.RenderRequest;
-import javax.portlet.RenderResponse;
-import javax.portlet.ResourceURL;
-
-import com.vaadin.Application;
-import com.vaadin.external.json.JSONException;
-import com.vaadin.external.json.JSONObject;
-import com.vaadin.terminal.DeploymentConfiguration;
-import com.vaadin.terminal.PaintException;
-import com.vaadin.terminal.WrappedRequest;
-import com.vaadin.terminal.WrappedResponse;
-import com.vaadin.terminal.gwt.client.ApplicationConfiguration;
-import com.vaadin.ui.Root;
-
-/**
- * TODO document me!
- *
- * @author peholmst
- *
- */
-@SuppressWarnings("serial")
-public class PortletCommunicationManager extends AbstractCommunicationManager {
-
- public PortletCommunicationManager(Application application) {
- super(application);
- }
-
- @Override
- protected BootstrapHandler createBootstrapHandler() {
- return new BootstrapHandler() {
- @Override
- public boolean handleRequest(Application application,
- WrappedRequest request, WrappedResponse response)
- throws IOException {
- PortletRequest portletRequest = WrappedPortletRequest.cast(
- request).getPortletRequest();
- if (portletRequest instanceof RenderRequest) {
- return super.handleRequest(application, request, response);
- } else {
- return false;
- }
- }
-
- @Override
- protected String getApplicationId(BootstrapContext context) {
- PortletRequest portletRequest = WrappedPortletRequest.cast(
- context.getRequest()).getPortletRequest();
- /*
- * We need to generate a unique ID because some portals already
- * create a DIV with the portlet's Window ID as the DOM ID.
- */
- return "v-" + portletRequest.getWindowID();
- }
-
- @Override
- protected String getAppUri(BootstrapContext context) {
- return getRenderResponse(context).createActionURL().toString();
- }
-
- private RenderResponse getRenderResponse(BootstrapContext context) {
- PortletResponse response = ((WrappedPortletResponse) context
- .getResponse()).getPortletResponse();
-
- RenderResponse renderResponse = (RenderResponse) response;
- return renderResponse;
- }
-
- @Override
- protected JSONObject getDefaultParameters(BootstrapContext context)
- throws JSONException {
- /*
- * 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
- */
- JSONObject defaults = super.getDefaultParameters(context);
-
- ResourceURL portletResourceUrl = getRenderResponse(context)
- .createResourceURL();
- portletResourceUrl
- .setResourceID(AbstractApplicationPortlet.RESOURCE_URL_ID);
- defaults.put(ApplicationConfiguration.PORTLET_RESOUCE_URL_BASE,
- portletResourceUrl.toString());
-
- defaults.put("pathInfo", "");
-
- return defaults;
- }
-
- @Override
- protected void appendMainScriptTagContents(
- BootstrapContext context, StringBuilder builder)
- throws JSONException, IOException {
- // fixed base theme to use - all portal pages with Vaadin
- // applications will load this exactly once
- String portalTheme = WrappedPortletRequest
- .cast(context.getRequest())
- .getPortalProperty(
- AbstractApplicationPortlet.PORTAL_PARAMETER_VAADIN_THEME);
- if (portalTheme != null
- && !portalTheme.equals(context.getThemeName())) {
- String portalThemeUri = getThemeUri(context, portalTheme);
- // XSS safe - originates from portal properties
- builder.append("vaadin.loadTheme('" + portalThemeUri
- + "');");
- }
-
- super.appendMainScriptTagContents(context, builder);
- }
-
- @Override
- protected String getMainDivStyle(BootstrapContext context) {
- DeploymentConfiguration deploymentConfiguration = context
- .getRequest().getDeploymentConfiguration();
- return deploymentConfiguration.getApplicationOrSystemProperty(
- AbstractApplicationPortlet.PORTLET_PARAMETER_STYLE,
- null);
- }
-
- @Override
- protected String getInitialUIDL(WrappedRequest request, Root root)
- throws PaintException, JSONException {
- return PortletCommunicationManager.this.getInitialUIDL(request,
- root);
- }
-
- @Override
- protected JSONObject getApplicationParameters(
- BootstrapContext context) throws JSONException,
- PaintException {
- JSONObject parameters = super.getApplicationParameters(context);
- WrappedPortletResponse wrappedPortletResponse = (WrappedPortletResponse) context
- .getResponse();
- MimeResponse portletResponse = (MimeResponse) wrappedPortletResponse
- .getPortletResponse();
- ResourceURL resourceURL = portletResponse.createResourceURL();
- resourceURL.setResourceID("browserDetails");
- parameters.put("browserDetailsUrl", resourceURL.toString());
- return parameters;
- }
-
- };
-
- }
-
- @Override
- protected InputStream getThemeResourceAsStream(Root root, String themeName,
- String resource) {
- PortletApplicationContext2 context = (PortletApplicationContext2) root
- .getApplication().getContext();
- PortletContext portletContext = context.getPortletSession()
- .getPortletContext();
- return portletContext.getResourceAsStream("/"
- + AbstractApplicationPortlet.THEME_DIRECTORY_PATH + themeName
- + "/" + resource);
- }
-
-}
diff --git a/src/com/vaadin/terminal/gwt/server/PortletRequestListener.java b/src/com/vaadin/terminal/gwt/server/PortletRequestListener.java
deleted file mode 100644
index 8a30f5c1d4..0000000000
--- a/src/com/vaadin/terminal/gwt/server/PortletRequestListener.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.terminal.gwt.server;
-
-import java.io.Serializable;
-
-import javax.portlet.PortletRequest;
-import javax.portlet.PortletResponse;
-import javax.servlet.Filter;
-
-import com.vaadin.Application;
-import com.vaadin.service.ApplicationContext.TransactionListener;
-import com.vaadin.terminal.Terminal;
-
-/**
- * An {@link Application} that implements this interface gets notified of
- * request start and end by the terminal. It is quite similar to the
- * {@link HttpServletRequestListener}, but the parameters are Portlet specific.
- * If an Application is deployed as both a Servlet and a Portlet, one most
- * likely needs to implement both.
- * <p>
- * Only JSR 286 style Portlets are supported.
- * <p>
- * The interface can be used for several helper tasks including:
- * <ul>
- * <li>Opening and closing database connections
- * <li>Implementing {@link ThreadLocal}
- * <li>Inter-portlet communication
- * </ul>
- * <p>
- * Alternatives for implementing similar features are are Servlet {@link Filter}
- * s and {@link TransactionListener}s in Vaadin.
- *
- * @since 6.2
- * @see HttpServletRequestListener
- */
-public interface PortletRequestListener extends Serializable {
-
- /**
- * This method is called before {@link Terminal} applies the request to
- * Application.
- *
- * @param requestData
- * the {@link PortletRequest} about to change Application state
- */
- public void onRequestStart(PortletRequest request, PortletResponse response);
-
- /**
- * This method is called at the end of each request.
- *
- * @param requestData
- * the {@link PortletRequest}
- */
- public void onRequestEnd(PortletRequest request, PortletResponse response);
-} \ No newline at end of file
diff --git a/src/com/vaadin/terminal/gwt/server/RequestTimer.java b/src/com/vaadin/terminal/gwt/server/RequestTimer.java
deleted file mode 100644
index 6c0edec466..0000000000
--- a/src/com/vaadin/terminal/gwt/server/RequestTimer.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal.gwt.server;
-
-import java.io.Serializable;
-
-/**
- * Times the handling of requests and stores the information as an attribute in
- * the request. The timing info is later passed on to the client in the UIDL and
- * the client provides JavaScript API for accessing this data from e.g.
- * TestBench.
- *
- * @author Jonatan Kronqvist / Vaadin Ltd
- */
-public class RequestTimer implements Serializable {
- private long requestStartTime = 0;
-
- /**
- * Starts the timing of a request. This should be called before any
- * processing of the request.
- */
- public void start() {
- requestStartTime = System.nanoTime();
- }
-
- /**
- * Stops the timing of a request. This should be called when all processing
- * of a request has finished.
- *
- * @param context
- */
- public void stop(AbstractWebApplicationContext context) {
- // Measure and store the total handling time. This data can be
- // used in TestBench 3 tests.
- long time = (System.nanoTime() - requestStartTime) / 1000000;
-
- // The timings must be stored in the context, since a new
- // RequestTimer is created for every request.
- context.setLastRequestTime(time);
- }
-}
diff --git a/src/com/vaadin/terminal/gwt/server/ResourceReference.java b/src/com/vaadin/terminal/gwt/server/ResourceReference.java
deleted file mode 100644
index 2104ad4b87..0000000000
--- a/src/com/vaadin/terminal/gwt/server/ResourceReference.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.terminal.gwt.server;
-
-import com.vaadin.Application;
-import com.vaadin.shared.communication.URLReference;
-import com.vaadin.terminal.ApplicationResource;
-import com.vaadin.terminal.ExternalResource;
-import com.vaadin.terminal.Resource;
-import com.vaadin.terminal.ThemeResource;
-
-public class ResourceReference extends URLReference {
-
- private Resource resource;
-
- public ResourceReference(Resource resource) {
- this.resource = resource;
- }
-
- public Resource getResource() {
- return resource;
- }
-
- @Override
- public String getURL() {
- if (resource instanceof ExternalResource) {
- return ((ExternalResource) resource).getURL();
- } else if (resource instanceof ApplicationResource) {
- final ApplicationResource r = (ApplicationResource) resource;
- final Application a = r.getApplication();
- if (a == null) {
- throw new RuntimeException(
- "An ApplicationResource ("
- + r.getClass().getName()
- + " must be attached to an application when it is sent to the client.");
- }
- final String uri = a.getRelativeLocation(r);
- return uri;
- } else if (resource instanceof ThemeResource) {
- final String uri = "theme://"
- + ((ThemeResource) resource).getResourceId();
- return uri;
- } else {
- throw new RuntimeException(getClass().getSimpleName()
- + " does not support resources of type: "
- + resource.getClass().getName());
- }
-
- }
-
- public static ResourceReference create(Resource resource) {
- if (resource == null) {
- return null;
- } else {
- return new ResourceReference(resource);
- }
- }
-
- public static Resource getResource(URLReference reference) {
- if (reference == null) {
- return null;
- }
- assert reference instanceof ResourceReference;
- return ((ResourceReference) reference).getResource();
- }
-}
diff --git a/src/com/vaadin/terminal/gwt/server/RestrictedRenderResponse.java b/src/com/vaadin/terminal/gwt/server/RestrictedRenderResponse.java
deleted file mode 100644
index 9fdffbf9a5..0000000000
--- a/src/com/vaadin/terminal/gwt/server/RestrictedRenderResponse.java
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-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.Collection;
-import java.util.Locale;
-
-import javax.portlet.CacheControl;
-import javax.portlet.PortletMode;
-import javax.portlet.PortletURL;
-import javax.portlet.RenderResponse;
-import javax.portlet.ResourceURL;
-import javax.servlet.http.Cookie;
-
-import org.w3c.dom.DOMException;
-import org.w3c.dom.Element;
-
-/**
- * Read-only wrapper for a {@link RenderResponse}.
- *
- * Only for use by {@link PortletApplicationContext} and
- * {@link PortletApplicationContext2}.
- */
-class RestrictedRenderResponse implements RenderResponse, Serializable {
-
- private RenderResponse response;
-
- RestrictedRenderResponse(RenderResponse response) {
- this.response = response;
- }
-
- @Override
- public void addProperty(String key, String value) {
- response.addProperty(key, value);
- }
-
- @Override
- public PortletURL createActionURL() {
- return response.createActionURL();
- }
-
- @Override
- public PortletURL createRenderURL() {
- return response.createRenderURL();
- }
-
- @Override
- public String encodeURL(String path) {
- return response.encodeURL(path);
- }
-
- @Override
- public void flushBuffer() throws IOException {
- // NOP
- // TODO throw?
- }
-
- @Override
- public int getBufferSize() {
- return response.getBufferSize();
- }
-
- @Override
- public String getCharacterEncoding() {
- return response.getCharacterEncoding();
- }
-
- @Override
- public String getContentType() {
- return response.getContentType();
- }
-
- @Override
- public Locale getLocale() {
- return response.getLocale();
- }
-
- @Override
- public String getNamespace() {
- return response.getNamespace();
- }
-
- @Override
- public OutputStream getPortletOutputStream() throws IOException {
- // write forbidden
- return null;
- }
-
- @Override
- public PrintWriter getWriter() throws IOException {
- // write forbidden
- return null;
- }
-
- @Override
- public boolean isCommitted() {
- return response.isCommitted();
- }
-
- @Override
- public void reset() {
- // NOP
- // TODO throw?
- }
-
- @Override
- public void resetBuffer() {
- // NOP
- // TODO throw?
- }
-
- @Override
- public void setBufferSize(int size) {
- // NOP
- // TODO throw?
- }
-
- @Override
- public void setContentType(String type) {
- // NOP
- // TODO throw?
- }
-
- @Override
- public void setProperty(String key, String value) {
- response.setProperty(key, value);
- }
-
- @Override
- public void setTitle(String title) {
- response.setTitle(title);
- }
-
- @Override
- public void setNextPossiblePortletModes(Collection<PortletMode> portletModes) {
- // NOP
- // TODO throw?
- }
-
- @Override
- public ResourceURL createResourceURL() {
- return response.createResourceURL();
- }
-
- @Override
- public CacheControl getCacheControl() {
- return response.getCacheControl();
- }
-
- @Override
- public void addProperty(Cookie cookie) {
- // NOP
- // TODO throw?
- }
-
- @Override
- public void addProperty(String key, Element element) {
- // NOP
- // TODO throw?
- }
-
- @Override
- public Element createElement(String tagName) throws DOMException {
- // NOP
- return null;
- }
-} \ No newline at end of file
diff --git a/src/com/vaadin/terminal/gwt/server/RpcManager.java b/src/com/vaadin/terminal/gwt/server/RpcManager.java
deleted file mode 100644
index 026c847e2b..0000000000
--- a/src/com/vaadin/terminal/gwt/server/RpcManager.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal.gwt.server;
-
-import java.io.Serializable;
-
-/**
- * Server side RPC manager that can invoke methods based on RPC calls received
- * from the client.
- *
- * @since 7.0
- */
-public interface RpcManager extends Serializable {
- public void applyInvocation(ServerRpcMethodInvocation invocation)
- throws RpcInvocationException;
-
- /**
- * Wrapper exception for exceptions which occur during invocation of an RPC
- * call
- *
- * @author Vaadin Ltd
- * @version @VERSION@
- * @since 7.0
- *
- */
- public static class RpcInvocationException extends Exception {
-
- public RpcInvocationException() {
- super();
- }
-
- public RpcInvocationException(String message, Throwable cause) {
- super(message, cause);
- }
-
- public RpcInvocationException(String message) {
- super(message);
- }
-
- public RpcInvocationException(Throwable cause) {
- super(cause);
- }
-
- }
-
-}
diff --git a/src/com/vaadin/terminal/gwt/server/RpcTarget.java b/src/com/vaadin/terminal/gwt/server/RpcTarget.java
deleted file mode 100644
index b280f5c6b5..0000000000
--- a/src/com/vaadin/terminal/gwt/server/RpcTarget.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal.gwt.server;
-
-import java.io.Serializable;
-
-import com.vaadin.terminal.VariableOwner;
-
-/**
- * Marker interface for server side classes that can receive RPC calls.
- *
- * This plays a role similar to that of {@link VariableOwner}.
- *
- * @since 7.0
- */
-public interface RpcTarget extends Serializable {
- /**
- * Returns the RPC manager instance to use when receiving calls for an RPC
- * interface.
- *
- * @param rpcInterface
- * interface for which the call was made
- * @return RpcManager or null if none found for the interface
- */
- public RpcManager getRpcManager(Class<?> rpcInterface);
-}
diff --git a/src/com/vaadin/terminal/gwt/server/ServerRpcManager.java b/src/com/vaadin/terminal/gwt/server/ServerRpcManager.java
deleted file mode 100644
index 1c7af82a36..0000000000
--- a/src/com/vaadin/terminal/gwt/server/ServerRpcManager.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal.gwt.server;
-
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.vaadin.shared.Connector;
-
-/**
- * Server side RPC manager that handles RPC calls coming from the client.
- *
- * Each {@link RpcTarget} (typically a {@link ClientConnector}) should have its
- * own instance of {@link ServerRpcManager} if it wants to receive RPC calls
- * from the client.
- *
- * @since 7.0
- */
-public class ServerRpcManager<T> implements RpcManager {
-
- private final T implementation;
- private final Class<T> rpcInterface;
-
- private static final Map<Class<?>, Class<?>> boxedTypes = new HashMap<Class<?>, Class<?>>();
- static {
- try {
- Class<?>[] boxClasses = new Class<?>[] { Boolean.class, Byte.class,
- Short.class, Character.class, Integer.class, Long.class,
- Float.class, Double.class };
- for (Class<?> boxClass : boxClasses) {
- Field typeField = boxClass.getField("TYPE");
- Class<?> primitiveType = (Class<?>) typeField.get(boxClass);
- boxedTypes.put(primitiveType, boxClass);
- }
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-
- /**
- * Create a RPC manager for an RPC target.
- *
- * @param target
- * RPC call target (normally a {@link Connector})
- * @param implementation
- * RPC interface implementation for the target
- * @param rpcInterface
- * RPC interface type
- */
- public ServerRpcManager(T implementation, Class<T> rpcInterface) {
- this.implementation = implementation;
- this.rpcInterface = rpcInterface;
- }
-
- /**
- * Invoke a method in a server side RPC target class. This method is to be
- * used by the RPC framework and unit testing tools only.
- *
- * @param target
- * non-null target of the RPC call
- * @param invocation
- * method invocation to perform
- * @throws RpcInvocationException
- */
- public static void applyInvocation(RpcTarget target,
- ServerRpcMethodInvocation invocation) throws RpcInvocationException {
- RpcManager manager = target.getRpcManager(invocation
- .getInterfaceClass());
- if (manager != null) {
- manager.applyInvocation(invocation);
- } else {
- getLogger()
- .log(Level.WARNING,
- "RPC call received for RpcTarget "
- + target.getClass().getName()
- + " ("
- + invocation.getConnectorId()
- + ") but the target has not registered any RPC interfaces");
- }
- }
-
- /**
- * Returns the RPC interface implementation for the RPC target.
- *
- * @return RPC interface implementation
- */
- protected T getImplementation() {
- return implementation;
- }
-
- /**
- * Returns the RPC interface type managed by this RPC manager instance.
- *
- * @return RPC interface type
- */
- protected Class<T> getRpcInterface() {
- return rpcInterface;
- }
-
- /**
- * Invoke a method in a server side RPC target class. This method is to be
- * used by the RPC framework and unit testing tools only.
- *
- * @param invocation
- * method invocation to perform
- */
- @Override
- public void applyInvocation(ServerRpcMethodInvocation invocation)
- throws RpcInvocationException {
- Method method = invocation.getMethod();
- Class<?>[] parameterTypes = method.getParameterTypes();
- Object[] args = new Object[parameterTypes.length];
- Object[] arguments = invocation.getParameters();
- for (int i = 0; i < args.length; i++) {
- // no conversion needed for basic cases
- // Class<?> type = parameterTypes[i];
- // if (type.isPrimitive()) {
- // type = boxedTypes.get(type);
- // }
- args[i] = arguments[i];
- }
- try {
- method.invoke(implementation, args);
- } catch (Exception e) {
- throw new RpcInvocationException("Unable to invoke method "
- + invocation.getMethodName() + " in "
- + invocation.getInterfaceName(), e);
- }
- }
-
- private static Logger getLogger() {
- return Logger.getLogger(ServerRpcManager.class.getName());
- }
-
-}
diff --git a/src/com/vaadin/terminal/gwt/server/ServerRpcMethodInvocation.java b/src/com/vaadin/terminal/gwt/server/ServerRpcMethodInvocation.java
deleted file mode 100644
index ff81a27596..0000000000
--- a/src/com/vaadin/terminal/gwt/server/ServerRpcMethodInvocation.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.terminal.gwt.server;
-
-import java.lang.reflect.Method;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-import com.vaadin.shared.communication.MethodInvocation;
-import com.vaadin.shared.communication.ServerRpc;
-
-public class ServerRpcMethodInvocation extends MethodInvocation {
-
- private static final Map<String, Method> invocationMethodCache = new ConcurrentHashMap<String, Method>(
- 128, 0.75f, 1);
-
- private final Method method;
-
- private Class<? extends ServerRpc> interfaceClass;
-
- public ServerRpcMethodInvocation(String connectorId, String interfaceName,
- String methodName, int parameterCount) {
- super(connectorId, interfaceName, methodName);
-
- interfaceClass = findClass();
- method = findInvocationMethod(interfaceClass, methodName,
- parameterCount);
- }
-
- private Class<? extends ServerRpc> findClass() {
- try {
- Class<?> rpcInterface = Class.forName(getInterfaceName());
- if (!ServerRpc.class.isAssignableFrom(rpcInterface)) {
- throw new IllegalArgumentException("The interface "
- + getInterfaceName() + "is not a server RPC interface.");
- }
- return (Class<? extends ServerRpc>) rpcInterface;
- } catch (ClassNotFoundException e) {
- throw new IllegalArgumentException("The server RPC interface "
- + getInterfaceName() + " could not be found", e);
- } finally {
-
- }
- }
-
- public Class<? extends ServerRpc> getInterfaceClass() {
- return interfaceClass;
- }
-
- public Method getMethod() {
- return method;
- }
-
- /**
- * Tries to find the method from the cache or alternatively by invoking
- * {@link #doFindInvocationMethod(Class, String, int)} and updating the
- * cache.
- *
- * @param targetType
- * @param methodName
- * @param parameterCount
- * @return
- */
- private Method findInvocationMethod(Class<?> targetType, String methodName,
- int parameterCount) {
- // TODO currently only using method name and number of parameters as the
- // signature
- String signature = targetType.getName() + "." + methodName + "("
- + parameterCount;
- Method invocationMethod = invocationMethodCache.get(signature);
-
- if (invocationMethod == null) {
- invocationMethod = doFindInvocationMethod(targetType, methodName,
- parameterCount);
-
- if (invocationMethod != null) {
- invocationMethodCache.put(signature, invocationMethod);
- }
- }
-
- if (invocationMethod == null) {
- throw new IllegalStateException("Can't find method " + methodName
- + " with " + parameterCount + " parameters in "
- + targetType.getName());
- }
-
- return invocationMethod;
- }
-
- /**
- * Tries to find the method from the class by looping through available
- * methods.
- *
- * @param targetType
- * @param methodName
- * @param parameterCount
- * @return
- */
- private Method doFindInvocationMethod(Class<?> targetType,
- String methodName, int parameterCount) {
- Method[] methods = targetType.getMethods();
- for (Method method : methods) {
- Class<?>[] parameterTypes = method.getParameterTypes();
- if (method.getName().equals(methodName)
- && parameterTypes.length == parameterCount) {
- return method;
- }
- }
- return null;
- }
-
-}
diff --git a/src/com/vaadin/terminal/gwt/server/ServletPortletHelper.java b/src/com/vaadin/terminal/gwt/server/ServletPortletHelper.java
deleted file mode 100644
index 2a1dc31897..0000000000
--- a/src/com/vaadin/terminal/gwt/server/ServletPortletHelper.java
+++ /dev/null
@@ -1,120 +0,0 @@
-package com.vaadin.terminal.gwt.server;
-
-import java.io.Serializable;
-
-import com.vaadin.Application;
-import com.vaadin.terminal.DeploymentConfiguration;
-import com.vaadin.terminal.WrappedRequest;
-import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.ui.Root;
-
-/*
- @VaadinApache2LicenseForJavaFiles@
- */
-
-class ServletPortletHelper implements Serializable {
- public static final String UPLOAD_URL_PREFIX = "APP/UPLOAD/";
-
- public static class ApplicationClassException extends Exception {
-
- public ApplicationClassException(String message, Throwable cause) {
- super(message, cause);
- }
-
- public ApplicationClassException(String message) {
- super(message);
- }
- }
-
- static Class<? extends Application> getApplicationClass(
- DeploymentConfiguration deploymentConfiguration)
- throws ApplicationClassException {
- String applicationParameter = deploymentConfiguration
- .getInitParameters().getProperty("application");
- String rootParameter = deploymentConfiguration.getInitParameters()
- .getProperty(Application.ROOT_PARAMETER);
- ClassLoader classLoader = deploymentConfiguration.getClassLoader();
-
- if (applicationParameter == null) {
-
- // Validate the parameter value
- verifyRootClass(rootParameter, classLoader);
-
- // Application can be used if a valid rootLayout is defined
- return Application.class;
- }
-
- try {
- return (Class<? extends Application>) classLoader
- .loadClass(applicationParameter);
- } catch (final ClassNotFoundException e) {
- throw new ApplicationClassException(
- "Failed to load application class: " + applicationParameter,
- e);
- }
- }
-
- private static void verifyRootClass(String className,
- ClassLoader classLoader) throws ApplicationClassException {
- if (className == null) {
- throw new ApplicationClassException(Application.ROOT_PARAMETER
- + " init parameter not defined");
- }
-
- // Check that the root layout class can be found
- try {
- Class<?> rootClass = classLoader.loadClass(className);
- if (!Root.class.isAssignableFrom(rootClass)) {
- throw new ApplicationClassException(className
- + " does not implement Root");
- }
- // Try finding a default constructor, else throw exception
- rootClass.getConstructor();
- } catch (ClassNotFoundException e) {
- throw new ApplicationClassException(className
- + " could not be loaded", e);
- } catch (SecurityException e) {
- throw new ApplicationClassException("Could not access " + className
- + " class", e);
- } catch (NoSuchMethodException e) {
- throw new ApplicationClassException(className
- + " doesn't have a public no-args constructor");
- }
- }
-
- private static boolean hasPathPrefix(WrappedRequest request, String prefix) {
- String pathInfo = request.getRequestPathInfo();
-
- if (pathInfo == null) {
- return false;
- }
-
- if (!prefix.startsWith("/")) {
- prefix = '/' + prefix;
- }
-
- if (pathInfo.startsWith(prefix)) {
- return true;
- }
-
- return false;
- }
-
- public static boolean isFileUploadRequest(WrappedRequest request) {
- return hasPathPrefix(request, UPLOAD_URL_PREFIX);
- }
-
- public static boolean isConnectorResourceRequest(WrappedRequest request) {
- return hasPathPrefix(request,
- ApplicationConnection.CONNECTOR_RESOURCE_PREFIX + "/");
- }
-
- public static boolean isUIDLRequest(WrappedRequest request) {
- return hasPathPrefix(request, ApplicationConnection.UIDL_REQUEST_PATH);
- }
-
- public static boolean isApplicationResourceRequest(WrappedRequest request) {
- return hasPathPrefix(request, ApplicationConnection.APP_REQUEST_PATH);
- }
-
-}
diff --git a/src/com/vaadin/terminal/gwt/server/SessionExpiredException.java b/src/com/vaadin/terminal/gwt/server/SessionExpiredException.java
deleted file mode 100644
index 37b76de443..0000000000
--- a/src/com/vaadin/terminal/gwt/server/SessionExpiredException.java
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.terminal.gwt.server;
-
-@SuppressWarnings("serial")
-public class SessionExpiredException extends Exception {
-
-}
diff --git a/src/com/vaadin/terminal/gwt/server/StreamingEndEventImpl.java b/src/com/vaadin/terminal/gwt/server/StreamingEndEventImpl.java
deleted file mode 100644
index 0d4963bd7d..0000000000
--- a/src/com/vaadin/terminal/gwt/server/StreamingEndEventImpl.java
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.terminal.gwt.server;
-
-import com.vaadin.terminal.StreamVariable.StreamingEndEvent;
-
-@SuppressWarnings("serial")
-final class StreamingEndEventImpl extends AbstractStreamingEvent implements
- StreamingEndEvent {
-
- public StreamingEndEventImpl(String filename, String type, long totalBytes) {
- super(filename, type, totalBytes, totalBytes);
- }
-
-}
diff --git a/src/com/vaadin/terminal/gwt/server/StreamingErrorEventImpl.java b/src/com/vaadin/terminal/gwt/server/StreamingErrorEventImpl.java
deleted file mode 100644
index 6ab3df2789..0000000000
--- a/src/com/vaadin/terminal/gwt/server/StreamingErrorEventImpl.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.terminal.gwt.server;
-
-import com.vaadin.terminal.StreamVariable.StreamingErrorEvent;
-
-@SuppressWarnings("serial")
-final class StreamingErrorEventImpl extends AbstractStreamingEvent implements
- StreamingErrorEvent {
-
- private final Exception exception;
-
- public StreamingErrorEventImpl(final String filename, final String type,
- long contentLength, long bytesReceived, final Exception exception) {
- super(filename, type, contentLength, bytesReceived);
- this.exception = exception;
- }
-
- @Override
- public final Exception getException() {
- return exception;
- }
-
-}
diff --git a/src/com/vaadin/terminal/gwt/server/StreamingProgressEventImpl.java b/src/com/vaadin/terminal/gwt/server/StreamingProgressEventImpl.java
deleted file mode 100644
index cfa7a1b98d..0000000000
--- a/src/com/vaadin/terminal/gwt/server/StreamingProgressEventImpl.java
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.terminal.gwt.server;
-
-import com.vaadin.terminal.StreamVariable.StreamingProgressEvent;
-
-@SuppressWarnings("serial")
-final class StreamingProgressEventImpl extends AbstractStreamingEvent implements
- StreamingProgressEvent {
-
- public StreamingProgressEventImpl(final String filename, final String type,
- long contentLength, long bytesReceived) {
- super(filename, type, contentLength, bytesReceived);
- }
-
-}
diff --git a/src/com/vaadin/terminal/gwt/server/StreamingStartEventImpl.java b/src/com/vaadin/terminal/gwt/server/StreamingStartEventImpl.java
deleted file mode 100644
index 274d05e111..0000000000
--- a/src/com/vaadin/terminal/gwt/server/StreamingStartEventImpl.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.terminal.gwt.server;
-
-import com.vaadin.terminal.StreamVariable.StreamingStartEvent;
-
-@SuppressWarnings("serial")
-final class StreamingStartEventImpl extends AbstractStreamingEvent implements
- StreamingStartEvent {
-
- private boolean disposed;
-
- public StreamingStartEventImpl(final String filename, final String type,
- long contentLength) {
- super(filename, type, contentLength, 0);
- }
-
- @Override
- public void disposeStreamVariable() {
- disposed = true;
- }
-
- boolean isDisposed() {
- return disposed;
- }
-
-}
diff --git a/src/com/vaadin/terminal/gwt/server/SystemMessageException.java b/src/com/vaadin/terminal/gwt/server/SystemMessageException.java
deleted file mode 100644
index d15ff8a7ef..0000000000
--- a/src/com/vaadin/terminal/gwt/server/SystemMessageException.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.terminal.gwt.server;
-
-@SuppressWarnings("serial")
-public class SystemMessageException extends RuntimeException {
-
- /**
- * Cause of the method exception
- */
- private Throwable cause;
-
- /**
- * Constructs a new <code>SystemMessageException</code> with the specified
- * detail message.
- *
- * @param msg
- * the detail message.
- */
- public SystemMessageException(String msg) {
- super(msg);
- }
-
- /**
- * Constructs a new <code>SystemMessageException</code> with the specified
- * detail message and cause.
- *
- * @param msg
- * the detail message.
- * @param cause
- * the cause of the exception.
- */
- public SystemMessageException(String msg, Throwable cause) {
- super(msg, cause);
- }
-
- /**
- * Constructs a new <code>SystemMessageException</code> from another
- * exception.
- *
- * @param cause
- * the cause of the exception.
- */
- public SystemMessageException(Throwable cause) {
- this.cause = cause;
- }
-
- /**
- * @see java.lang.Throwable#getCause()
- */
- @Override
- public Throwable getCause() {
- return cause;
- }
-
-} \ No newline at end of file
diff --git a/src/com/vaadin/terminal/gwt/server/UnsupportedBrowserHandler.java b/src/com/vaadin/terminal/gwt/server/UnsupportedBrowserHandler.java
deleted file mode 100644
index 5248af595e..0000000000
--- a/src/com/vaadin/terminal/gwt/server/UnsupportedBrowserHandler.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.terminal.gwt.server;
-
-import java.io.IOException;
-import java.io.Writer;
-
-import com.vaadin.Application;
-import com.vaadin.terminal.RequestHandler;
-import com.vaadin.terminal.WrappedRequest;
-import com.vaadin.terminal.WrappedResponse;
-
-/**
- * A {@link RequestHandler} that presents an informative page if the browser in
- * use is unsupported. Recognizes Chrome Frame and allow it to be used.
- *
- * <p>
- * This handler is usually added to the application by
- * {@link AbstractCommunicationManager}.
- * </p>
- */
-@SuppressWarnings("serial")
-public class UnsupportedBrowserHandler implements RequestHandler {
-
- /** Cookie used to ignore browser checks */
- public static final String FORCE_LOAD_COOKIE = "vaadinforceload=1";
-
- @Override
- public boolean handleRequest(Application application,
- WrappedRequest request, WrappedResponse response)
- throws IOException {
-
- if (request.getBrowserDetails() != null) {
- // Check if the browser is supported
- // If Chrome Frame is available we'll assume it's ok
- WebBrowser b = request.getBrowserDetails().getWebBrowser();
- if (b.isTooOldToFunctionProperly() && !b.isChromeFrameCapable()) {
- // bypass if cookie set
- String c = request.getHeader("Cookie");
- if (c == null || !c.contains(FORCE_LOAD_COOKIE)) {
- writeBrowserTooOldPage(request, response);
- return true; // request handled
- }
- }
- }
-
- return false; // pass to next handler
- }
-
- /**
- * Writes a page encouraging the user to upgrade to a more current browser.
- *
- * @param request
- * @param response
- * @throws IOException
- */
- protected void writeBrowserTooOldPage(WrappedRequest request,
- WrappedResponse response) throws IOException {
- Writer page = response.getWriter();
- WebBrowser b = request.getBrowserDetails().getWebBrowser();
-
- page.write("<html><body><h1>I'm sorry, but your browser is not supported</h1>"
- + "<p>The version ("
- + b.getBrowserMajorVersion()
- + "."
- + b.getBrowserMinorVersion()
- + ") of the browser you are using "
- + " is outdated and not supported.</p>"
- + "<p>You should <b>consider upgrading</b> to a more up-to-date browser.</p> "
- + "<p>The most popular browsers are <b>"
- + " <a href=\"https://www.google.com/chrome\">Chrome</a>,"
- + " <a href=\"http://www.mozilla.com/firefox\">Firefox</a>,"
- + (b.isWindows() ? " <a href=\"http://windows.microsoft.com/en-US/internet-explorer/downloads/ie\">Internet Explorer</a>,"
- : "")
- + " <a href=\"http://www.opera.com/browser\">Opera</a>"
- + " and <a href=\"http://www.apple.com/safari\">Safari</a>.</b><br/>"
- + "Upgrading to the latest version of one of these <b>will make the web safer, faster and better looking.</b></p>"
- + (b.isIE() ? "<script type=\"text/javascript\" src=\"http://ajax.googleapis.com/ajax/libs/chrome-frame/1/CFInstall.min.js\"></script>"
- + "<p>If you can not upgrade your browser, please consider trying <a onclick=\"CFInstall.check({mode:'overlay'});return false;\" href=\"http://www.google.com/chromeframe\">Chrome Frame</a>.</p>"
- : "") //
- + "<p><sub><a onclick=\"document.cookie='"
- + FORCE_LOAD_COOKIE
- + "';window.location.reload();return false;\" href=\"#\">Continue without updating</a> (not recommended)</sub></p>"
- + "</body>\n" + "</html>");
-
- page.close();
- }
-} \ No newline at end of file
diff --git a/src/com/vaadin/terminal/gwt/server/UploadException.java b/src/com/vaadin/terminal/gwt/server/UploadException.java
deleted file mode 100644
index 58253da0fb..0000000000
--- a/src/com/vaadin/terminal/gwt/server/UploadException.java
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.terminal.gwt.server;
-
-@SuppressWarnings("serial")
-public class UploadException extends Exception {
- public UploadException(Exception e) {
- super("Upload failed", e);
- }
-
- public UploadException(String msg) {
- super(msg);
- }
-}
diff --git a/src/com/vaadin/terminal/gwt/server/VaadinContext.java b/src/com/vaadin/terminal/gwt/server/VaadinContext.java
deleted file mode 100644
index f03044a872..0000000000
--- a/src/com/vaadin/terminal/gwt/server/VaadinContext.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal.gwt.server;
-
-import java.lang.reflect.Method;
-import java.util.Iterator;
-
-import com.vaadin.event.EventRouter;
-import com.vaadin.terminal.DeploymentConfiguration;
-import com.vaadin.tools.ReflectTools;
-
-public class VaadinContext {
- private static final Method BOOTSTRAP_GENERATE_METHOD = ReflectTools
- .findMethod(BootstrapListener.class, "modifyBootstrap",
- BootstrapResponse.class);
-
- private final DeploymentConfiguration deploymentConfiguration;
-
- private final EventRouter eventRouter = new EventRouter();
-
- public VaadinContext(DeploymentConfiguration deploymentConfiguration) {
- this.deploymentConfiguration = deploymentConfiguration;
- deploymentConfiguration.setVaadinContext(this);
- }
-
- public DeploymentConfiguration getDeploymentConfiguration() {
- return deploymentConfiguration;
- }
-
- public void init() {
- VaadinContextEvent event = new VaadinContextEvent(this);
- Iterator<VaadinContextListener> listeners = deploymentConfiguration
- .getContextListeners();
- while (listeners.hasNext()) {
- VaadinContextListener listener = listeners.next();
- listener.contextCreated(event);
- }
- }
-
- public void destroy() {
- VaadinContextEvent event = new VaadinContextEvent(this);
- Iterator<VaadinContextListener> listeners = deploymentConfiguration
- .getContextListeners();
- while (listeners.hasNext()) {
- VaadinContextListener listener = listeners.next();
- listener.contextDestoryed(event);
- }
- }
-
- public void addBootstrapListener(BootstrapListener listener) {
- eventRouter.addListener(BootstrapResponse.class, listener,
- BOOTSTRAP_GENERATE_METHOD);
- }
-
- public void fireModifyBootstrapEvent(BootstrapResponse bootstrapResponse) {
- eventRouter.fireEvent(bootstrapResponse);
- }
-
-}
diff --git a/src/com/vaadin/terminal/gwt/server/VaadinContextEvent.java b/src/com/vaadin/terminal/gwt/server/VaadinContextEvent.java
deleted file mode 100644
index 239490433c..0000000000
--- a/src/com/vaadin/terminal/gwt/server/VaadinContextEvent.java
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal.gwt.server;
-
-import java.util.EventObject;
-
-public class VaadinContextEvent extends EventObject {
-
- public VaadinContextEvent(VaadinContext source) {
- super(source);
- }
-
- public VaadinContext getVaadinContext() {
- return (VaadinContext) getSource();
- }
-
-}
diff --git a/src/com/vaadin/terminal/gwt/server/VaadinContextListener.java b/src/com/vaadin/terminal/gwt/server/VaadinContextListener.java
deleted file mode 100644
index 5e379d9b91..0000000000
--- a/src/com/vaadin/terminal/gwt/server/VaadinContextListener.java
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal.gwt.server;
-
-import java.util.EventListener;
-
-public interface VaadinContextListener extends EventListener {
- public void contextCreated(VaadinContextEvent event);
-
- public void contextDestoryed(VaadinContextEvent event);
-}
diff --git a/src/com/vaadin/terminal/gwt/server/WebApplicationContext.java b/src/com/vaadin/terminal/gwt/server/WebApplicationContext.java
deleted file mode 100644
index 36c08b2ed9..0000000000
--- a/src/com/vaadin/terminal/gwt/server/WebApplicationContext.java
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal.gwt.server;
-
-import java.io.File;
-import java.util.Enumeration;
-import java.util.HashMap;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpSession;
-import javax.servlet.http.HttpSessionBindingEvent;
-import javax.servlet.http.HttpSessionBindingListener;
-
-import com.vaadin.Application;
-
-/**
- * Web application context for Vaadin applications.
- *
- * This is automatically added as a {@link HttpSessionBindingListener} when
- * added to a {@link HttpSession}.
- *
- * @author Vaadin Ltd.
- * @version
- * @VERSION@
- * @since 3.1
- */
-@SuppressWarnings("serial")
-public class WebApplicationContext extends AbstractWebApplicationContext {
-
- protected transient HttpSession session;
- private transient boolean reinitializingSession = false;
-
- /**
- * Stores a reference to the currentRequest. Null it not inside a request.
- */
- private transient Object currentRequest = null;
-
- /**
- * Creates a new Web Application Context.
- *
- */
- protected WebApplicationContext() {
-
- }
-
- @Override
- protected void startTransaction(Application application, Object request) {
- currentRequest = request;
- super.startTransaction(application, request);
- }
-
- @Override
- protected void endTransaction(Application application, Object request) {
- super.endTransaction(application, request);
- currentRequest = null;
- }
-
- @Override
- public void valueUnbound(HttpSessionBindingEvent event) {
- if (!reinitializingSession) {
- // Avoid closing the application if we are only reinitializing the
- // session. Closing the application would cause the state to be lost
- // and a new application to be created, which is not what we want.
- super.valueUnbound(event);
- }
- }
-
- /**
- * Discards the current session and creates a new session with the same
- * contents. The purpose of this is to introduce a new session key in order
- * to avoid session fixation attacks.
- */
- @SuppressWarnings("unchecked")
- public void reinitializeSession() {
-
- HttpSession oldSession = getHttpSession();
-
- // Stores all attributes (security key, reference to this context
- // instance) so they can be added to the new session
- HashMap<String, Object> attrs = new HashMap<String, Object>();
- for (Enumeration<String> e = oldSession.getAttributeNames(); e
- .hasMoreElements();) {
- String name = e.nextElement();
- attrs.put(name, oldSession.getAttribute(name));
- }
-
- // Invalidate the current session, set flag to avoid call to
- // valueUnbound
- reinitializingSession = true;
- oldSession.invalidate();
- reinitializingSession = false;
-
- // Create a new session
- HttpSession newSession = ((HttpServletRequest) currentRequest)
- .getSession();
-
- // Restores all attributes (security key, reference to this context
- // instance)
- for (String name : attrs.keySet()) {
- newSession.setAttribute(name, attrs.get(name));
- }
-
- // Update the "current session" variable
- session = newSession;
- }
-
- /**
- * Gets the application context base directory.
- *
- * @see com.vaadin.service.ApplicationContext#getBaseDirectory()
- */
- @Override
- public File getBaseDirectory() {
- final String realPath = ApplicationServlet.getResourcePath(
- session.getServletContext(), "/");
- if (realPath == null) {
- return null;
- }
- return new File(realPath);
- }
-
- /**
- * Gets the http-session application is running in.
- *
- * @return HttpSession this application context resides in.
- */
- public HttpSession getHttpSession() {
- return session;
- }
-
- /**
- * Gets the application context for an HttpSession.
- *
- * @param session
- * the HTTP session.
- * @return the application context for HttpSession.
- */
- static public WebApplicationContext getApplicationContext(
- HttpSession session) {
- WebApplicationContext cx = (WebApplicationContext) session
- .getAttribute(WebApplicationContext.class.getName());
- if (cx == null) {
- cx = new WebApplicationContext();
- session.setAttribute(WebApplicationContext.class.getName(), cx);
- }
- if (cx.session == null) {
- cx.session = session;
- }
- return cx;
- }
-
- protected void addApplication(Application application) {
- applications.add(application);
- }
-
- /**
- * Gets communication manager for an application.
- *
- * If this application has not been running before, a new manager is
- * created.
- *
- * @param application
- * @return CommunicationManager
- */
- public CommunicationManager getApplicationManager(Application application,
- AbstractApplicationServlet servlet) {
- CommunicationManager mgr = (CommunicationManager) applicationToAjaxAppMgrMap
- .get(application);
-
- if (mgr == null) {
- // Creates new manager
- mgr = servlet.createCommunicationManager(application);
- applicationToAjaxAppMgrMap.put(application, mgr);
- }
- return mgr;
- }
-
-}
diff --git a/src/com/vaadin/terminal/gwt/server/WebBrowser.java b/src/com/vaadin/terminal/gwt/server/WebBrowser.java
deleted file mode 100644
index 4b92b12b66..0000000000
--- a/src/com/vaadin/terminal/gwt/server/WebBrowser.java
+++ /dev/null
@@ -1,462 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal.gwt.server;
-
-import java.util.Date;
-import java.util.Locale;
-
-import com.vaadin.shared.VBrowserDetails;
-import com.vaadin.terminal.Terminal;
-import com.vaadin.terminal.WrappedRequest;
-
-/**
- * Class that provides information about the web browser the user is using.
- * Provides information such as browser name and version, screen resolution and
- * IP address.
- *
- * @author Vaadin Ltd.
- * @version @VERSION@
- */
-public class WebBrowser implements Terminal {
-
- private int screenHeight = 0;
- private int screenWidth = 0;
- private String browserApplication = null;
- private Locale locale;
- private String address;
- private boolean secureConnection;
- private int timezoneOffset = 0;
- private int rawTimezoneOffset = 0;
- private int dstSavings;
- private boolean dstInEffect;
- private boolean touchDevice;
-
- private VBrowserDetails browserDetails;
- private long clientServerTimeDelta;
-
- /**
- * There is no default-theme for this terminal type.
- *
- * @return Always returns null.
- */
-
- @Override
- public String getDefaultTheme() {
- return null;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.terminal.Terminal#getScreenHeight()
- */
-
- @Override
- public int getScreenHeight() {
- return screenHeight;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.terminal.Terminal#getScreenWidth()
- */
-
- @Override
- public int getScreenWidth() {
- return screenWidth;
- }
-
- /**
- * Get the browser user-agent string.
- *
- * @return The raw browser userAgent string
- */
- public String getBrowserApplication() {
- return browserApplication;
- }
-
- /**
- * Gets the IP-address of the web browser. If the application is running
- * inside a portlet, this method will return null.
- *
- * @return IP-address in 1.12.123.123 -format
- */
- public String getAddress() {
- return address;
- }
-
- /** Get the default locate of the browser. */
- public Locale getLocale() {
- return locale;
- }
-
- /** Is the connection made using HTTPS? */
- public boolean isSecureConnection() {
- return secureConnection;
- }
-
- /**
- * Tests whether the user is using Firefox.
- *
- * @return true if the user is using Firefox, false if the user is not using
- * Firefox or if no information on the browser is present
- */
- public boolean isFirefox() {
- if (browserDetails == null) {
- return false;
- }
-
- return browserDetails.isFirefox();
- }
-
- /**
- * Tests whether the user is using Internet Explorer.
- *
- * @return true if the user is using Internet Explorer, false if the user is
- * not using Internet Explorer or if no information on the browser
- * is present
- */
- public boolean isIE() {
- if (browserDetails == null) {
- return false;
- }
-
- return browserDetails.isIE();
- }
-
- /**
- * Tests whether the user is using Safari.
- *
- * @return true if the user is using Safari, false if the user is not using
- * Safari or if no information on the browser is present
- */
- public boolean isSafari() {
- if (browserDetails == null) {
- return false;
- }
-
- return browserDetails.isSafari();
- }
-
- /**
- * Tests whether the user is using Opera.
- *
- * @return true if the user is using Opera, false if the user is not using
- * Opera or if no information on the browser is present
- */
- public boolean isOpera() {
- if (browserDetails == null) {
- return false;
- }
-
- return browserDetails.isOpera();
- }
-
- /**
- * Tests whether the user is using Chrome.
- *
- * @return true if the user is using Chrome, false if the user is not using
- * Chrome or if no information on the browser is present
- */
- public boolean isChrome() {
- if (browserDetails == null) {
- return false;
- }
-
- return browserDetails.isChrome();
- }
-
- /**
- * Tests whether the user is using Chrome Frame.
- *
- * @return true if the user is using Chrome Frame, false if the user is not
- * using Chrome or if no information on the browser is present
- */
- public boolean isChromeFrame() {
- if (browserDetails == null) {
- return false;
- }
-
- return browserDetails.isChromeFrame();
- }
-
- /**
- * Tests whether the user's browser is Chrome Frame capable.
- *
- * @return true if the user can use Chrome Frame, false if the user can not
- * or if no information on the browser is present
- */
- public boolean isChromeFrameCapable() {
- if (browserDetails == null) {
- return false;
- }
-
- return browserDetails.isChromeFrameCapable();
- }
-
- /**
- * Gets the major version of the browser the user is using.
- *
- * <p>
- * Note that Internet Explorer in IE7 compatibility mode might return 8 in
- * some cases even though it should return 7.
- * </p>
- *
- * @return The major version of the browser or -1 if not known.
- */
- public int getBrowserMajorVersion() {
- if (browserDetails == null) {
- return -1;
- }
-
- return browserDetails.getBrowserMajorVersion();
- }
-
- /**
- * Gets the minor version of the browser the user is using.
- *
- * @see #getBrowserMajorVersion()
- *
- * @return The minor version of the browser or -1 if not known.
- */
- public int getBrowserMinorVersion() {
- if (browserDetails == null) {
- return -1;
- }
-
- return browserDetails.getBrowserMinorVersion();
- }
-
- /**
- * Tests whether the user is using Linux.
- *
- * @return true if the user is using Linux, false if the user is not using
- * Linux or if no information on the browser is present
- */
- public boolean isLinux() {
- return browserDetails.isLinux();
- }
-
- /**
- * Tests whether the user is using Mac OS X.
- *
- * @return true if the user is using Mac OS X, false if the user is not
- * using Mac OS X or if no information on the browser is present
- */
- public boolean isMacOSX() {
- return browserDetails.isMacOSX();
- }
-
- /**
- * Tests whether the user is using Windows.
- *
- * @return true if the user is using Windows, false if the user is not using
- * Windows or if no information on the browser is present
- */
- public boolean isWindows() {
- return browserDetails.isWindows();
- }
-
- /**
- * Returns the browser-reported TimeZone offset in milliseconds from GMT.
- * This includes possible daylight saving adjustments, to figure out which
- * TimeZone the user actually might be in, see
- * {@link #getRawTimezoneOffset()}.
- *
- * @see WebBrowser#getRawTimezoneOffset()
- * @return timezone offset in milliseconds, 0 if not available
- */
- public Integer getTimezoneOffset() {
- return timezoneOffset;
- }
-
- /**
- * Returns the browser-reported TimeZone offset in milliseconds from GMT
- * ignoring possible daylight saving adjustments that may be in effect in
- * the browser.
- * <p>
- * You can use this to figure out which TimeZones the user could actually be
- * in by calling {@link TimeZone#getAvailableIDs(int)}.
- * </p>
- * <p>
- * If {@link #getRawTimezoneOffset()} and {@link #getTimezoneOffset()}
- * returns the same value, the browser is either in a zone that does not
- * currently have daylight saving time, or in a zone that never has daylight
- * saving time.
- * </p>
- *
- * @return timezone offset in milliseconds excluding DST, 0 if not available
- */
- public Integer getRawTimezoneOffset() {
- return rawTimezoneOffset;
- }
-
- /**
- * Gets the difference in minutes between the browser's GMT TimeZone and
- * DST.
- *
- * @return the amount of minutes that the TimeZone shifts when DST is in
- * effect
- */
- public int getDSTSavings() {
- return dstSavings;
- }
-
- /**
- * Determines whether daylight savings time (DST) is currently in effect in
- * the region of the browser or not.
- *
- * @return true if the browser resides at a location that currently is in
- * DST
- */
- public boolean isDSTInEffect() {
- return dstInEffect;
- }
-
- /**
- * Returns the current date and time of the browser. This will not be
- * entirely accurate due to varying network latencies, but should provide a
- * close-enough value for most cases. Also note that the returned Date
- * object uses servers default time zone, not the clients.
- *
- * @return the current date and time of the browser.
- * @see #isDSTInEffect()
- * @see #getDSTSavings()
- * @see #getTimezoneOffset()
- */
- public Date getCurrentDate() {
- return new Date(new Date().getTime() + clientServerTimeDelta);
- }
-
- /**
- * @return true if the browser is detected to support touch events
- */
- public boolean isTouchDevice() {
- return touchDevice;
- }
-
- /**
- * For internal use by AbstractApplicationServlet/AbstractApplicationPortlet
- * only. Updates all properties in the class according to the given
- * information.
- *
- * @param sw
- * Screen width
- * @param sh
- * Screen height
- * @param tzo
- * TimeZone offset in minutes from GMT
- * @param rtzo
- * raw TimeZone offset in minutes from GMT (w/o DST adjustment)
- * @param dstSavings
- * the difference between the raw TimeZone and DST in minutes
- * @param dstInEffect
- * is DST currently active in the region or not?
- * @param curDate
- * the current date in milliseconds since the epoch
- * @param touchDevice
- */
- void updateClientSideDetails(String sw, String sh, String tzo, String rtzo,
- String dstSavings, String dstInEffect, String curDate,
- boolean touchDevice) {
- if (sw != null) {
- try {
- screenHeight = Integer.parseInt(sh);
- screenWidth = Integer.parseInt(sw);
- } catch (final NumberFormatException e) {
- screenHeight = screenWidth = 0;
- }
- }
- if (tzo != null) {
- try {
- // browser->java conversion: min->ms, reverse sign
- timezoneOffset = -Integer.parseInt(tzo) * 60 * 1000;
- } catch (final NumberFormatException e) {
- timezoneOffset = 0; // default gmt+0
- }
- }
- if (rtzo != null) {
- try {
- // browser->java conversion: min->ms, reverse sign
- rawTimezoneOffset = -Integer.parseInt(rtzo) * 60 * 1000;
- } catch (final NumberFormatException e) {
- rawTimezoneOffset = 0; // default gmt+0
- }
- }
- if (dstSavings != null) {
- try {
- // browser->java conversion: min->ms
- this.dstSavings = Integer.parseInt(dstSavings) * 60 * 1000;
- } catch (final NumberFormatException e) {
- this.dstSavings = 0; // default no savings
- }
- }
- if (dstInEffect != null) {
- this.dstInEffect = Boolean.parseBoolean(dstInEffect);
- }
- if (curDate != null) {
- try {
- long curTime = Long.parseLong(curDate);
- clientServerTimeDelta = curTime - new Date().getTime();
- } catch (final NumberFormatException e) {
- clientServerTimeDelta = 0;
- }
- }
- this.touchDevice = touchDevice;
-
- }
-
- /**
- * For internal use by AbstractApplicationServlet/AbstractApplicationPortlet
- * only. Updates all properties in the class according to the given
- * information.
- *
- * @param request
- * the wrapped request to read the information from
- */
- void updateRequestDetails(WrappedRequest request) {
- locale = request.getLocale();
- address = request.getRemoteAddr();
- secureConnection = request.isSecure();
- String agent = request.getHeader("user-agent");
-
- if (agent != null) {
- browserApplication = agent;
- browserDetails = new VBrowserDetails(agent);
- }
-
- if (request.getParameter("sw") != null) {
- updateClientSideDetails(request.getParameter("sw"),
- request.getParameter("sh"), request.getParameter("tzo"),
- request.getParameter("rtzo"), request.getParameter("dstd"),
- request.getParameter("dston"),
- request.getParameter("curdate"),
- request.getParameter("td") != null);
- }
- }
-
- /**
- * Checks if the browser is so old that it simply won't work with a Vaadin
- * application. Can be used to redirect to an alternative page, show
- * alternative content or similar.
- *
- * When this method returns true chances are very high that the browser
- * won't work and it does not make sense to direct the user to the Vaadin
- * application.
- *
- * @return true if the browser won't work, false if not the browser is
- * supported or might work
- */
- public boolean isTooOldToFunctionProperly() {
- if (browserDetails == null) {
- // Don't know, so assume it will work
- return false;
- }
-
- return browserDetails.isTooOldToFunctionProperly();
- }
-
-}
diff --git a/src/com/vaadin/terminal/gwt/server/WrappedHttpServletRequest.java b/src/com/vaadin/terminal/gwt/server/WrappedHttpServletRequest.java
deleted file mode 100644
index cf58f398af..0000000000
--- a/src/com/vaadin/terminal/gwt/server/WrappedHttpServletRequest.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal.gwt.server;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletRequestWrapper;
-
-import com.vaadin.Application;
-import com.vaadin.terminal.CombinedRequest;
-import com.vaadin.terminal.DeploymentConfiguration;
-import com.vaadin.terminal.WrappedRequest;
-
-/**
- * Wrapper for {@link HttpServletRequest}.
- *
- * @author Vaadin Ltd.
- * @since 7.0
- *
- * @see WrappedRequest
- * @see WrappedHttpServletResponse
- */
-public class WrappedHttpServletRequest extends HttpServletRequestWrapper
- implements WrappedRequest {
-
- private final DeploymentConfiguration deploymentConfiguration;
-
- /**
- * Wraps a http servlet request and associates with a deployment
- * configuration
- *
- * @param request
- * the http servlet request to wrap
- * @param deploymentConfiguration
- * the associated deployment configuration
- */
- public WrappedHttpServletRequest(HttpServletRequest request,
- DeploymentConfiguration deploymentConfiguration) {
- super(request);
- this.deploymentConfiguration = deploymentConfiguration;
- }
-
- @Override
- public String getRequestPathInfo() {
- return getPathInfo();
- }
-
- @Override
- public int getSessionMaxInactiveInterval() {
- return getSession().getMaxInactiveInterval();
- }
-
- @Override
- public Object getSessionAttribute(String name) {
- return getSession().getAttribute(name);
- }
-
- @Override
- public void setSessionAttribute(String name, Object attribute) {
- getSession().setAttribute(name, attribute);
- }
-
- /**
- * Gets the original, unwrapped HTTP servlet request.
- *
- * @return the servlet request
- */
- public HttpServletRequest getHttpServletRequest() {
- return this;
- }
-
- @Override
- public DeploymentConfiguration getDeploymentConfiguration() {
- return deploymentConfiguration;
- }
-
- @Override
- public BrowserDetails getBrowserDetails() {
- return new BrowserDetails() {
- @Override
- public String getUriFragment() {
- return null;
- }
-
- @Override
- public String getWindowName() {
- return null;
- }
-
- @Override
- public WebBrowser getWebBrowser() {
- WebApplicationContext context = (WebApplicationContext) Application
- .getCurrent().getContext();
- return context.getBrowser();
- }
- };
- }
-
- /**
- * Helper method to get a <code>WrappedHttpServletRequest</code> from a
- * <code>WrappedRequest</code>. Aside from casting, this method also takes
- * care of situations where there's another level of wrapping.
- *
- * @param request
- * a wrapped request
- * @return a wrapped http servlet request
- * @throws ClassCastException
- * if the wrapped request doesn't wrap a http servlet request
- */
- public static WrappedHttpServletRequest cast(WrappedRequest request) {
- if (request instanceof CombinedRequest) {
- CombinedRequest combinedRequest = (CombinedRequest) request;
- request = combinedRequest.getSecondRequest();
- }
- return (WrappedHttpServletRequest) request;
- }
-} \ No newline at end of file
diff --git a/src/com/vaadin/terminal/gwt/server/WrappedHttpServletResponse.java b/src/com/vaadin/terminal/gwt/server/WrappedHttpServletResponse.java
deleted file mode 100644
index 32b2f352a8..0000000000
--- a/src/com/vaadin/terminal/gwt/server/WrappedHttpServletResponse.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal.gwt.server;
-
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpServletResponseWrapper;
-
-import com.vaadin.terminal.DeploymentConfiguration;
-import com.vaadin.terminal.WrappedResponse;
-
-/**
- * Wrapper for {@link HttpServletResponse}.
- *
- * @author Vaadin Ltd.
- * @since 7.0
- *
- * @see WrappedResponse
- * @see WrappedHttpServletRequest
- */
-public class WrappedHttpServletResponse extends HttpServletResponseWrapper
- implements WrappedResponse {
-
- private DeploymentConfiguration deploymentConfiguration;
-
- /**
- * Wraps a http servlet response and an associated deployment configuration
- *
- * @param response
- * the http servlet response to wrap
- * @param deploymentConfiguration
- * the associated deployment configuration
- */
- public WrappedHttpServletResponse(HttpServletResponse response,
- DeploymentConfiguration deploymentConfiguration) {
- super(response);
- this.deploymentConfiguration = deploymentConfiguration;
- }
-
- /**
- * Gets the original unwrapped <code>HttpServletResponse</code>
- *
- * @return the unwrapped response
- */
- public HttpServletResponse getHttpServletResponse() {
- return this;
- }
-
- @Override
- public void setCacheTime(long milliseconds) {
- doSetCacheTime(this, milliseconds);
- }
-
- // Implementation shared with WrappedPortletResponse
- static void doSetCacheTime(WrappedResponse response, long milliseconds) {
- if (milliseconds <= 0) {
- response.setHeader("Cache-Control", "no-cache");
- response.setHeader("Pragma", "no-cache");
- response.setDateHeader("Expires", 0);
- } else {
- response.setHeader("Cache-Control", "max-age=" + milliseconds
- / 1000);
- response.setDateHeader("Expires", System.currentTimeMillis()
- + milliseconds);
- // Required to apply caching in some Tomcats
- response.setHeader("Pragma", "cache");
- }
- }
-
- @Override
- public DeploymentConfiguration getDeploymentConfiguration() {
- return deploymentConfiguration;
- }
-} \ No newline at end of file
diff --git a/src/com/vaadin/terminal/gwt/server/WrappedPortletRequest.java b/src/com/vaadin/terminal/gwt/server/WrappedPortletRequest.java
deleted file mode 100644
index a3fa172034..0000000000
--- a/src/com/vaadin/terminal/gwt/server/WrappedPortletRequest.java
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal.gwt.server;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Locale;
-import java.util.Map;
-
-import javax.portlet.ClientDataRequest;
-import javax.portlet.PortletRequest;
-import javax.portlet.ResourceRequest;
-
-import com.vaadin.Application;
-import com.vaadin.terminal.CombinedRequest;
-import com.vaadin.terminal.DeploymentConfiguration;
-import com.vaadin.terminal.WrappedRequest;
-import com.vaadin.terminal.gwt.client.ApplicationConnection;
-
-/**
- * Wrapper for {@link PortletRequest} and its subclasses.
- *
- * @author Vaadin Ltd.
- * @since 7.0
- *
- * @see WrappedRequest
- * @see WrappedPortletResponse
- */
-public class WrappedPortletRequest implements WrappedRequest {
-
- private final PortletRequest request;
- private final DeploymentConfiguration deploymentConfiguration;
-
- /**
- * Wraps a portlet request and an associated deployment configuration
- *
- * @param request
- * the portlet request to wrap
- * @param deploymentConfiguration
- * the associated deployment configuration
- */
- public WrappedPortletRequest(PortletRequest request,
- DeploymentConfiguration deploymentConfiguration) {
- this.request = request;
- this.deploymentConfiguration = deploymentConfiguration;
- }
-
- @Override
- public Object getAttribute(String name) {
- return request.getAttribute(name);
- }
-
- @Override
- public int getContentLength() {
- try {
- return ((ClientDataRequest) request).getContentLength();
- } catch (ClassCastException e) {
- throw new IllegalStateException(
- "Content lenght only available for ClientDataRequests");
- }
- }
-
- @Override
- public InputStream getInputStream() throws IOException {
- try {
- return ((ClientDataRequest) request).getPortletInputStream();
- } catch (ClassCastException e) {
- throw new IllegalStateException(
- "Input data only available for ClientDataRequests");
- }
- }
-
- @Override
- public String getParameter(String name) {
- return request.getParameter(name);
- }
-
- @Override
- public Map<String, String[]> getParameterMap() {
- return request.getParameterMap();
- }
-
- @Override
- public void setAttribute(String name, Object o) {
- request.setAttribute(name, o);
- }
-
- @Override
- public String getRequestPathInfo() {
- if (request instanceof ResourceRequest) {
- ResourceRequest resourceRequest = (ResourceRequest) request;
- String resourceID = resourceRequest.getResourceID();
- if (AbstractApplicationPortlet.RESOURCE_URL_ID.equals(resourceID)) {
- String resourcePath = resourceRequest
- .getParameter(ApplicationConnection.V_RESOURCE_PATH);
- return resourcePath;
- }
- return resourceID;
- } else {
- return null;
- }
- }
-
- @Override
- public int getSessionMaxInactiveInterval() {
- return request.getPortletSession().getMaxInactiveInterval();
- }
-
- @Override
- public Object getSessionAttribute(String name) {
- return request.getPortletSession().getAttribute(name);
- }
-
- @Override
- public void setSessionAttribute(String name, Object attribute) {
- request.getPortletSession().setAttribute(name, attribute);
- }
-
- /**
- * Gets the original, unwrapped portlet request.
- *
- * @return the unwrapped portlet request
- */
- public PortletRequest getPortletRequest() {
- return request;
- }
-
- @Override
- public String getContentType() {
- try {
- return ((ResourceRequest) request).getContentType();
- } catch (ClassCastException e) {
- throw new IllegalStateException(
- "Content type only available for ResourceRequests");
- }
- }
-
- @Override
- public BrowserDetails getBrowserDetails() {
- return new BrowserDetails() {
- @Override
- public String getUriFragment() {
- return null;
- }
-
- @Override
- public String getWindowName() {
- return null;
- }
-
- @Override
- public WebBrowser getWebBrowser() {
- PortletApplicationContext2 context = (PortletApplicationContext2) Application
- .getCurrent().getContext();
- return context.getBrowser();
- }
- };
- }
-
- @Override
- public Locale getLocale() {
- return request.getLocale();
- }
-
- @Override
- public String getRemoteAddr() {
- return null;
- }
-
- @Override
- public boolean isSecure() {
- return request.isSecure();
- }
-
- @Override
- public String getHeader(String string) {
- return null;
- }
-
- /**
- * Reads a portal property from the portal context of the wrapped request.
- *
- * @param name
- * a string with the name of the portal property to get
- * @return a string with the value of the property, or <code>null</code> if
- * the property is not defined
- */
- public String getPortalProperty(String name) {
- return request.getPortalContext().getProperty(name);
- }
-
- @Override
- public DeploymentConfiguration getDeploymentConfiguration() {
- return deploymentConfiguration;
- }
-
- /**
- * Helper method to get a <code>WrappedPortlettRequest</code> from a
- * <code>WrappedRequest</code>. Aside from casting, this method also takes
- * care of situations where there's another level of wrapping.
- *
- * @param request
- * a wrapped request
- * @return a wrapped portlet request
- * @throws ClassCastException
- * if the wrapped request doesn't wrap a portlet request
- */
- public static WrappedPortletRequest cast(WrappedRequest request) {
- if (request instanceof CombinedRequest) {
- CombinedRequest combinedRequest = (CombinedRequest) request;
- request = combinedRequest.getSecondRequest();
- }
- return (WrappedPortletRequest) request;
- }
-}
diff --git a/src/com/vaadin/terminal/gwt/server/WrappedPortletResponse.java b/src/com/vaadin/terminal/gwt/server/WrappedPortletResponse.java
deleted file mode 100644
index f7ecf26f3c..0000000000
--- a/src/com/vaadin/terminal/gwt/server/WrappedPortletResponse.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal.gwt.server;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.PrintWriter;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.Locale;
-import java.util.TimeZone;
-
-import javax.portlet.MimeResponse;
-import javax.portlet.PortletResponse;
-import javax.portlet.ResourceResponse;
-
-import com.vaadin.terminal.DeploymentConfiguration;
-import com.vaadin.terminal.WrappedResponse;
-
-/**
- * Wrapper for {@link PortletResponse} and its subclasses.
- *
- * @author Vaadin Ltd.
- * @since 7.0
- *
- * @see WrappedResponse
- * @see WrappedPortletRequest
- */
-public class WrappedPortletResponse implements WrappedResponse {
- private static final DateFormat HTTP_DATE_FORMAT = new SimpleDateFormat(
- "EEE, dd MMM yyyy HH:mm:ss zzz", Locale.ENGLISH);
- static {
- HTTP_DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("GMT"));
- }
-
- private final PortletResponse response;
- private DeploymentConfiguration deploymentConfiguration;
-
- /**
- * Wraps a portlet response and an associated deployment configuration
- *
- * @param response
- * the portlet response to wrap
- * @param deploymentConfiguration
- * the associated deployment configuration
- */
- public WrappedPortletResponse(PortletResponse response,
- DeploymentConfiguration deploymentConfiguration) {
- this.response = response;
- this.deploymentConfiguration = deploymentConfiguration;
- }
-
- @Override
- public OutputStream getOutputStream() throws IOException {
- return ((MimeResponse) response).getPortletOutputStream();
- }
-
- /**
- * Gets the original, unwrapped portlet response.
- *
- * @return the unwrapped portlet response
- */
- public PortletResponse getPortletResponse() {
- return response;
- }
-
- @Override
- public void setContentType(String type) {
- ((MimeResponse) response).setContentType(type);
- }
-
- @Override
- public PrintWriter getWriter() throws IOException {
- return ((MimeResponse) response).getWriter();
- }
-
- @Override
- public void setStatus(int responseStatus) {
- response.setProperty(ResourceResponse.HTTP_STATUS_CODE,
- Integer.toString(responseStatus));
- }
-
- @Override
- public void setHeader(String name, String value) {
- response.setProperty(name, value);
- }
-
- @Override
- public void setDateHeader(String name, long timestamp) {
- response.setProperty(name, HTTP_DATE_FORMAT.format(new Date(timestamp)));
- }
-
- @Override
- public void setCacheTime(long milliseconds) {
- WrappedHttpServletResponse.doSetCacheTime(this, milliseconds);
- }
-
- @Override
- public void sendError(int errorCode, String message) throws IOException {
- setStatus(errorCode);
- getWriter().write(message);
- }
-
- @Override
- public DeploymentConfiguration getDeploymentConfiguration() {
- return deploymentConfiguration;
- }
-} \ No newline at end of file