summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArtur Signell <artur@vaadin.com>2013-03-27 14:57:50 +0200
committerVaadin Code Review <review@vaadin.com>2013-04-03 13:01:43 +0000
commit3c479dd00b24acad23e7c97e7283e31299d771d1 (patch)
tree436156b439ae7952829bec24a247e486ac8ac107
parentad290f8c65057bdef33ec73cb49a8c6d10b9e356 (diff)
downloadvaadin-framework-3c479dd00b24acad23e7c97e7283e31299d771d1.tar.gz
vaadin-framework-3c479dd00b24acad23e7c97e7283e31299d771d1.zip
Refactored how all requests are handled by VaadinServlet and VaadinPortlet (#11192)
* Handling is now based on a list of RequestHandlers in VaadinService * Request handling logic has been moved to VaadinService * Users can customize the list by adding own (service level) request handlers * For users specific request handlers you can still use the request handlers in VaadinSession * Deprecated RequestType - all handlers are given the opportunity to handle a request until one of them chooses to handle it. RequestType makes no sense as it does not tell which handler will handle the request. * Removed serveStaticResource which has never been used Change-Id: Ia7d088535e46430ca8adf631d3f1dd944b9d51e2
-rw-r--r--server/src/com/vaadin/server/BootstrapHandler.java6
-rw-r--r--server/src/com/vaadin/server/ConnectorResourceHandler.java86
-rw-r--r--server/src/com/vaadin/server/GAEVaadinServlet.java40
-rw-r--r--server/src/com/vaadin/server/LegacyCommunicationManager.java8
-rw-r--r--server/src/com/vaadin/server/VaadinPortlet.java255
-rw-r--r--server/src/com/vaadin/server/VaadinPortletService.java64
-rw-r--r--server/src/com/vaadin/server/VaadinService.java169
-rw-r--r--server/src/com/vaadin/server/VaadinServlet.java252
-rw-r--r--server/src/com/vaadin/server/VaadinServletService.java133
-rw-r--r--server/src/com/vaadin/server/communication/FileUploadHandler.java3
-rw-r--r--server/src/com/vaadin/server/communication/HeartbeatHandler.java6
-rw-r--r--server/src/com/vaadin/server/communication/PortletDummyRequestHandler.java82
-rw-r--r--server/src/com/vaadin/server/communication/PortletUIInitHandler.java63
-rw-r--r--server/src/com/vaadin/server/communication/PublishedFileHandler.java4
-rw-r--r--server/src/com/vaadin/server/communication/ServletUIInitHandler.java33
-rw-r--r--server/src/com/vaadin/server/communication/SessionRequestHandler.java8
-rw-r--r--server/src/com/vaadin/server/communication/UIInitHandler.java9
-rw-r--r--server/src/com/vaadin/server/communication/UidlRequestHandler.java7
18 files changed, 658 insertions, 570 deletions
diff --git a/server/src/com/vaadin/server/BootstrapHandler.java b/server/src/com/vaadin/server/BootstrapHandler.java
index 9c603ae7ed..80cadb02c1 100644
--- a/server/src/com/vaadin/server/BootstrapHandler.java
+++ b/server/src/com/vaadin/server/BootstrapHandler.java
@@ -115,6 +115,12 @@ public abstract class BootstrapHandler extends SynchronizedRequestHandler {
@Override
public boolean synchronizedHandleRequest(VaadinSession session,
VaadinRequest request, VaadinResponse response) throws IOException {
+ String pathInfo = request.getPathInfo();
+ if (pathInfo.startsWith("/" + ApplicationConstants.APP_PATH + "/")) {
+ // We do not want to handle /APP requests here, instead let it fall
+ // through and produce a 404
+ return false;
+ }
try {
List<UIProvider> uiProviders = session.getUIProviders();
diff --git a/server/src/com/vaadin/server/ConnectorResourceHandler.java b/server/src/com/vaadin/server/ConnectorResourceHandler.java
index 12c6df6ffa..00d82988d3 100644
--- a/server/src/com/vaadin/server/ConnectorResourceHandler.java
+++ b/server/src/com/vaadin/server/ConnectorResourceHandler.java
@@ -48,60 +48,50 @@ public class ConnectorResourceHandler implements RequestHandler {
return false;
}
Matcher matcher = CONNECTOR_RESOURCE_PATTERN.matcher(requestPath);
- if (matcher.matches()) {
- String uiId = matcher.group(1);
- String cid = matcher.group(2);
- String key = matcher.group(3);
-
- session.lock();
- UI ui;
- ClientConnector connector;
- try {
- ui = session.getUIById(Integer.parseInt(uiId));
- if (ui == null) {
- return error(request, response,
- "Ignoring connector request for no-existent root "
- + uiId);
- }
-
- connector = ui.getConnectorTracker().getConnector(cid);
- if (connector == null) {
- return error(request, response,
- "Ignoring connector request for no-existent connector "
- + cid + " in root " + uiId);
- }
+ if (!matcher.matches()) {
+ return false;
+ }
+ String uiId = matcher.group(1);
+ String cid = matcher.group(2);
+ String key = matcher.group(3);
- } finally {
- session.unlock();
+ session.lock();
+ UI ui;
+ ClientConnector connector;
+ try {
+ ui = session.getUIById(Integer.parseInt(uiId));
+ if (ui == null) {
+ return error(request, response,
+ "Ignoring connector request for no-existent root "
+ + uiId);
}
- Map<Class<?>, CurrentInstance> oldThreadLocals = CurrentInstance
- .setThreadLocals(ui);
- try {
- if (!connector.handleConnectorRequest(request, response, key)) {
- return error(request, response,
- connector.getClass().getSimpleName() + " ("
- + connector.getConnectorId()
- + ") did not handle connector request for "
- + key);
- }
- } finally {
- CurrentInstance.restoreThreadLocals(oldThreadLocals);
+ connector = ui.getConnectorTracker().getConnector(cid);
+ if (connector == null) {
+ return error(request, response,
+ "Ignoring connector request for no-existent connector "
+ + cid + " in root " + uiId);
}
- return true;
- } else if (requestPath.matches('/' + ApplicationConstants.APP_PATH
- + "(/.*)?")) {
- /*
- * This should be the last request handler before we get to
- * bootstrap logic. Prevent /APP requests from reaching bootstrap
- * handlers to help protect the /APP name space for framework usage.
- */
- return error(request, response,
- "Returning 404 for /APP request not yet handled.");
- } else {
- return false;
+ } finally {
+ session.unlock();
}
+
+ Map<Class<?>, CurrentInstance> oldThreadLocals = CurrentInstance
+ .setThreadLocals(ui);
+ try {
+ if (!connector.handleConnectorRequest(request, response, key)) {
+ return error(request, response, connector.getClass()
+ .getSimpleName()
+ + " ("
+ + connector.getConnectorId()
+ + ") did not handle connector request for " + key);
+ }
+ } finally {
+ CurrentInstance.restoreThreadLocals(oldThreadLocals);
+ }
+
+ return true;
}
private static boolean error(VaadinRequest request,
diff --git a/server/src/com/vaadin/server/GAEVaadinServlet.java b/server/src/com/vaadin/server/GAEVaadinServlet.java
index 0d2063d446..b4a83603b0 100644
--- a/server/src/com/vaadin/server/GAEVaadinServlet.java
+++ b/server/src/com/vaadin/server/GAEVaadinServlet.java
@@ -184,16 +184,14 @@ public class GAEVaadinServlet extends VaadinServlet {
return;
}
- RequestType requestType = getRequestType(request);
-
- if (requestType == RequestType.STATIC_FILE) {
+ if (isStaticResourceRequest(request)) {
// no locking needed, let superclass handle
super.service(request, response);
cleanSession(request);
return;
}
- if (requestType == RequestType.APP) {
+ if (ServletPortletHelper.isAppRequest(request)) {
// no locking needed, let superclass handle
getApplicationContext(request,
MemcacheServiceFactory.getMemcacheService());
@@ -205,7 +203,11 @@ public class GAEVaadinServlet extends VaadinServlet {
final HttpSession session = request.getSession(getService()
.requestCanCreateSession(request));
if (session == null) {
- handleServiceSessionExpired(request, response);
+ try {
+ getService().handleSessionExpired(request, response);
+ } catch (ServiceException e) {
+ throw new ServletException(e);
+ }
cleanSession(request);
return;
}
@@ -218,19 +220,21 @@ public class GAEVaadinServlet extends VaadinServlet {
// 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 (!ServletPortletHelper.isUIDLRequest(request)) {
+ while (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);
+ }
}
}
diff --git a/server/src/com/vaadin/server/LegacyCommunicationManager.java b/server/src/com/vaadin/server/LegacyCommunicationManager.java
index b956b806bd..2f559e4b26 100644
--- a/server/src/com/vaadin/server/LegacyCommunicationManager.java
+++ b/server/src/com/vaadin/server/LegacyCommunicationManager.java
@@ -65,10 +65,6 @@ public class LegacyCommunicationManager implements Serializable {
// TODO PUSH move
public static final String WRITE_SECURITY_TOKEN_FLAG = "writeSecurityToken";
- private static final RequestHandler UNSUPPORTED_BROWSER_HANDLER = new UnsupportedBrowserHandler();
-
- private static final RequestHandler CONNECTOR_RESOURCE_HANDLER = new ConnectorResourceHandler();
-
/**
* TODO Document me!
*
@@ -112,10 +108,6 @@ public class LegacyCommunicationManager implements Serializable {
*/
public LegacyCommunicationManager(VaadinSession session) {
this.session = session;
- session.addRequestHandler(session.getService().createBootstrapHandler(
- session));
- session.addRequestHandler(UNSUPPORTED_BROWSER_HANDLER);
- session.addRequestHandler(CONNECTOR_RESOURCE_HANDLER);
requireLocale(session.getLocale().toString());
}
diff --git a/server/src/com/vaadin/server/VaadinPortlet.java b/server/src/com/vaadin/server/VaadinPortlet.java
index 9dd8a4c94b..6aa7546b16 100644
--- a/server/src/com/vaadin/server/VaadinPortlet.java
+++ b/server/src/com/vaadin/server/VaadinPortlet.java
@@ -17,17 +17,14 @@ package com.vaadin.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.Method;
-import java.net.MalformedURLException;
import java.util.Enumeration;
import java.util.Map;
import java.util.Properties;
-import java.util.logging.Level;
import java.util.logging.Logger;
import javax.portlet.ActionRequest;
@@ -46,18 +43,11 @@ 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.server.LegacyCommunicationManager.Callback;
-import com.vaadin.server.communication.FileUploadHandler;
-import com.vaadin.server.communication.HeartbeatHandler;
-import com.vaadin.server.communication.PortletListenerNotifier;
-import com.vaadin.server.communication.PublishedFileHandler;
-import com.vaadin.server.communication.SessionRequestHandler;
-import com.vaadin.server.communication.UIInitHandler;
-import com.vaadin.server.communication.UidlRequestHandler;
+import com.vaadin.server.communication.PortletDummyRequestHandler;
+import com.vaadin.server.communication.PortletUIInitHandler;
import com.vaadin.util.CurrentInstance;
/**
@@ -207,24 +197,6 @@ public class VaadinPortlet extends GenericPortlet implements Constants,
}
- public static class AbstractApplicationPortletWrapper implements Callback {
-
- private final VaadinPortlet portlet;
-
- public AbstractApplicationPortletWrapper(VaadinPortlet portlet) {
- this.portlet = portlet;
- }
-
- @Override
- public void criticalNotification(VaadinRequest request,
- VaadinResponse response, String cap, String msg,
- String details, String outOfSyncURL) throws IOException {
- portlet.criticalNotification((VaadinPortletRequest) request,
- (VaadinPortletResponse) 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.
@@ -287,6 +259,7 @@ public class VaadinPortlet extends GenericPortlet implements Constants,
vaadinService.setCurrentInstances(null, null);
portletInitialized();
+
CurrentInstance.clearAll();
}
@@ -307,8 +280,10 @@ public class VaadinPortlet extends GenericPortlet implements Constants,
/**
* @author Vaadin Ltd
*
- * @deprecated As of 7.0. Will likely change or be removed in a future
- * version
+ * @deprecated As of 7.0. This is no longer used and only provided for
+ * backwards compatibility. Each {@link RequestHandler} can
+ * individually decide whether it wants to handle a request or
+ * not.
*/
@Deprecated
protected enum RequestType {
@@ -319,8 +294,10 @@ public class VaadinPortlet extends GenericPortlet implements Constants,
* @param vaadinRequest
* @return
*
- * @deprecated As of 7.0. Will likely change or be removed in a future
- * version
+ * @deprecated As of 7.0. This is no longer used and only provided for
+ * backwards compatibility. Each {@link RequestHandler} can
+ * individually decide whether it wants to handle a request or
+ * not.
*/
@Deprecated
protected RequestType getRequestType(VaadinPortletRequest vaadinRequest) {
@@ -331,7 +308,7 @@ public class VaadinPortlet extends GenericPortlet implements Constants,
ResourceRequest resourceRequest = (ResourceRequest) request;
if (ServletPortletHelper.isUIDLRequest(vaadinRequest)) {
return RequestType.UIDL;
- } else if (isBrowserDetailsRequest(resourceRequest)) {
+ } else if (PortletUIInitHandler.isUIInitRequest(vaadinRequest)) {
return RequestType.BROWSER_DETAILS;
} else if (ServletPortletHelper.isFileUploadRequest(vaadinRequest)) {
return RequestType.FILE_UPLOAD;
@@ -342,7 +319,7 @@ public class VaadinPortlet extends GenericPortlet implements Constants,
return RequestType.APP;
} else if (ServletPortletHelper.isHeartbeatRequest(vaadinRequest)) {
return RequestType.HEARTBEAT;
- } else if (isDummyRequest(resourceRequest)) {
+ } else if (PortletDummyRequestHandler.isDummyRequest(vaadinRequest)) {
return RequestType.DUMMY;
} else {
return RequestType.STATIC_FILE;
@@ -355,16 +332,6 @@ public class VaadinPortlet extends GenericPortlet implements Constants,
return RequestType.UNKNOWN;
}
- private boolean isBrowserDetailsRequest(ResourceRequest request) {
- return request.getResourceID() != null
- && request.getResourceID().equals("v-browserDetails");
- }
-
- private boolean isDummyRequest(ResourceRequest request) {
- return request.getResourceID() != null
- && request.getResourceID().equals("DUMMY");
- }
-
/**
* @param request
* @param response
@@ -380,93 +347,11 @@ public class VaadinPortlet extends GenericPortlet implements Constants,
CurrentInstance.clearAll();
setCurrent(this);
- handleRequest(createVaadinRequest(request),
- createVaadinResponse(response));
- }
-
- protected void handleRequest(VaadinPortletRequest request,
- VaadinPortletResponse response) throws PortletException,
- IOException {
- getService().requestStart(request, response);
-
- VaadinPortletSession vaadinSession = null;
try {
- AbstractApplicationPortletWrapper portletWrapper = new AbstractApplicationPortletWrapper(
- this);
-
- RequestType requestType = getRequestType(request);
-
- if (requestType == RequestType.UNKNOWN) {
- handleUnknownRequest(request, response);
- } else if (requestType == RequestType.DUMMY) {
- /*
- * This dummy page is used by action responses to redirect to,
- * in order to prevent the boot strap code from being rendered
- * into strange places such as iframes.
- */
- ((ResourceResponse) response).setContentType("text/html");
- final OutputStream out = ((ResourceResponse) response)
- .getPortletOutputStream();
- final PrintWriter outWriter = new PrintWriter(
- new BufferedWriter(new OutputStreamWriter(out, "UTF-8")));
- outWriter.print("<html><body>dummy page</body></html>");
- outWriter.close();
- } else if (requestType == RequestType.STATIC_FILE) {
- serveStaticResources((ResourceRequest) request,
- (ResourceResponse) response);
- } else {
- try {
- vaadinSession = (VaadinPortletSession) getService()
- .findVaadinSession(request);
- if (vaadinSession == null) {
- return;
- }
-
- if (requestType == RequestType.PUBLISHED_FILE) {
- new PublishedFileHandler().handleRequest(vaadinSession,
- request, response);
- return;
- } else if (requestType == RequestType.HEARTBEAT) {
- new HeartbeatHandler().handleRequest(vaadinSession,
- request, response);
- return;
- }
-
- // Notify listeners
- new PortletListenerNotifier().handleRequest(vaadinSession,
- request, response);
-
- /* Handle the request */
- if (requestType == RequestType.FILE_UPLOAD) {
- new FileUploadHandler().handleRequest(vaadinSession,
- request, response);
- return;
- } else if (requestType == RequestType.BROWSER_DETAILS) {
- new UIInitHandler().handleRequest(vaadinSession,
- request, response);
- return;
- } else if (requestType == RequestType.UIDL) {
- // Handles AJAX UIDL requests
- new UidlRequestHandler(portletWrapper).handleRequest(
- vaadinSession, request, response);
-
- return;
- } else {
- handleOtherRequest(request, response, requestType,
- vaadinSession,
- vaadinSession.getCommunicationManager());
- }
- } catch (final SessionExpiredException e) {
- // TODO Figure out a better way to deal with
- // SessionExpiredExceptions
- getLogger().finest("A user session has expired");
- } catch (final Throwable e) {
- handleServiceException(request, response, vaadinSession, e);
-
- }
- }
- } finally {
- getService().requestEnd(request, response, vaadinSession);
+ getService().handleRequest(createVaadinRequest(request),
+ createVaadinResponse(response));
+ } catch (ServiceException e) {
+ throw new PortletException(e);
}
}
@@ -498,80 +383,12 @@ public class VaadinPortlet extends GenericPortlet implements Constants,
return vaadinService;
}
- private void handleUnknownRequest(VaadinPortletRequest request,
- VaadinPortletResponse 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 vaadinSession
- * @param vaadinSession
- * @param communicationManager
- * @throws PortletException
- * @throws IOException
- * @throws MalformedURLException
- */
- private void handleOtherRequest(VaadinPortletRequest request,
- VaadinResponse response, RequestType requestType,
- VaadinSession vaadinSession,
- LegacyCommunicationManager communicationManager)
- throws PortletException, IOException, MalformedURLException {
- if (requestType == RequestType.APP || requestType == RequestType.RENDER) {
- if (!new SessionRequestHandler().handleRequest(vaadinSession,
- 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().log(Level.INFO,
- "Requested resource [{0}] could not be found", resourceID);
- response.setProperty(ResourceResponse.HTTP_STATUS_CODE,
- Integer.toString(HttpServletResponse.SC_NOT_FOUND));
- }
- }
-
@Override
public void processAction(ActionRequest request, ActionResponse response)
throws PortletException, IOException {
@@ -606,44 +423,6 @@ public class VaadinPortlet extends GenericPortlet implements Constants,
handleRequest(request, response);
}
- private void handleServiceException(VaadinPortletRequest request,
- VaadinPortletResponse response, VaadinSession vaadinSession,
- Throwable e) throws IOException, PortletException {
- // TODO Check that this error handler is working when running inside a
- // portlet
- if (vaadinSession != null) {
- vaadinSession.lock();
- }
- try {
- // if this was an UIDL request, response UIDL back to client
- ErrorHandler errorHandler = ErrorEvent
- .findErrorHandler(vaadinSession);
- if (getRequestType(request) == RequestType.UIDL) {
- SystemMessages ci = getService().getSystemMessages(
- ServletPortletHelper.findLocale(null, vaadinSession,
- request), request);
- criticalNotification(request, response,
- ci.getInternalErrorCaption(),
- ci.getInternalErrorMessage(), null,
- ci.getInternalErrorURL());
- if (errorHandler != null) {
- errorHandler.error(new ErrorEvent(e));
- }
- } else {
- if (errorHandler != null) {
- errorHandler.error(new ErrorEvent(e));
- } else {
- // Re-throw other exceptions
- throw new PortletException(e);
- }
- }
- } finally {
- if (vaadinSession != null) {
- vaadinSession.unlock();
- }
- }
- }
-
/**
* Send notification to client's application. Used to notify client of
* critical errors and session expiration due to long inactivity. Server has
diff --git a/server/src/com/vaadin/server/VaadinPortletService.java b/server/src/com/vaadin/server/VaadinPortletService.java
index 6023f6448b..b9dcfa5768 100644
--- a/server/src/com/vaadin/server/VaadinPortletService.java
+++ b/server/src/com/vaadin/server/VaadinPortletService.java
@@ -17,17 +17,23 @@
package com.vaadin.server;
import java.io.File;
+import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
+import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
+import javax.portlet.EventRequest;
import javax.portlet.PortletContext;
import javax.portlet.PortletRequest;
-
+import javax.portlet.RenderRequest;
import com.vaadin.server.VaadinPortlet.RequestType;
import com.vaadin.server.communication.PortletBootstrapHandler;
+import com.vaadin.server.communication.PortletDummyRequestHandler;
+import com.vaadin.server.communication.PortletListenerNotifier;
+import com.vaadin.server.communication.PortletUIInitHandler;
import com.vaadin.ui.UI;
public class VaadinPortletService extends VaadinService {
@@ -49,6 +55,35 @@ public class VaadinPortletService extends VaadinService {
}
}
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.vaadin.server.LegacyCommunicationManager.Callback#criticalNotification
+ * (com.vaadin.server.VaadinRequest, com.vaadin.server.VaadinResponse,
+ * java.lang.String, java.lang.String, java.lang.String, java.lang.String)
+ */
+ @Deprecated
+ @Override
+ public void criticalNotification(VaadinRequest request,
+ VaadinResponse response, String cap, String msg, String details,
+ String url) throws IOException {
+ getPortlet().criticalNotification((VaadinPortletRequest) request,
+ (VaadinPortletResponse) response, cap, msg, details, url);
+ }
+
+ @Override
+ protected List<RequestHandler> createRequestHandlers() {
+ List<RequestHandler> handlers = super.createRequestHandlers();
+
+ handlers.add(new PortletUIInitHandler());
+ handlers.add(new PortletListenerNotifier());
+ handlers.add(0, new PortletDummyRequestHandler());
+ handlers.add(0, new PortletBootstrapHandler());
+
+ return handlers;
+ }
+
/**
* Retrieves a reference to the portlet associated with this service.
*
@@ -163,13 +198,19 @@ public class VaadinPortletService extends VaadinService {
@Override
protected boolean requestCanCreateSession(VaadinRequest request) {
- RequestType requestType = getRequestType(request);
- if (requestType == RequestType.RENDER) {
+ if (!(request instanceof VaadinPortletRequest)) {
+ throw new IllegalArgumentException(
+ "Request is not a VaadinPortletRequest");
+ }
+
+ PortletRequest portletRequest = ((VaadinPortletRequest) request)
+ .getPortletRequest();
+ if (portletRequest instanceof RenderRequest) {
// In most cases the first request is a render request that
// renders the HTML fragment. This should create a Vaadin
// session unless there is already one.
return true;
- } else if (requestType == RequestType.EVENT) {
+ } else if (portletRequest instanceof EventRequest) {
// 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.
@@ -254,8 +295,19 @@ public class VaadinPortletService extends VaadinService {
return "v-" + portletRequest.getWindowID();
}
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.vaadin.server.VaadinService#handleSessionExpired(com.vaadin.server
+ * .VaadinRequest, com.vaadin.server.VaadinResponse)
+ */
@Override
- protected BootstrapHandler createBootstrapHandler(VaadinSession session) {
- return new PortletBootstrapHandler();
+ protected void handleSessionExpired(VaadinRequest request,
+ VaadinResponse response) {
+ // TODO Figure out a better way to deal with
+ // SessionExpiredExceptions
+ getLogger().finest("A user session has expired");
}
+
}
diff --git a/server/src/com/vaadin/server/VaadinService.java b/server/src/com/vaadin/server/VaadinService.java
index e4970d4104..3b088294e3 100644
--- a/server/src/com/vaadin/server/VaadinService.java
+++ b/server/src/com/vaadin/server/VaadinService.java
@@ -17,6 +17,7 @@
package com.vaadin.server;
import java.io.File;
+import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.lang.reflect.Constructor;
@@ -24,7 +25,9 @@ import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
+import java.util.List;
import java.util.Locale;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
@@ -33,9 +36,16 @@ import java.util.logging.Logger;
import javax.portlet.PortletContext;
import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletResponse;
import com.vaadin.annotations.PreserveOnRefresh;
import com.vaadin.event.EventRouter;
+import com.vaadin.server.LegacyCommunicationManager.Callback;
+import com.vaadin.server.communication.FileUploadHandler;
+import com.vaadin.server.communication.HeartbeatHandler;
+import com.vaadin.server.communication.PublishedFileHandler;
+import com.vaadin.server.communication.SessionRequestHandler;
+import com.vaadin.server.communication.UidlRequestHandler;
import com.vaadin.shared.ui.ui.UIConstants;
import com.vaadin.ui.UI;
import com.vaadin.util.CurrentInstance;
@@ -49,7 +59,7 @@ import com.vaadin.util.ReflectTools;
*
* @since 7.0
*/
-public abstract class VaadinService implements Serializable {
+public abstract class VaadinService implements Serializable, Callback {
static final String REINITIALIZING_SESSION_MARKER = VaadinService.class
.getName() + ".reinitializing";
@@ -83,6 +93,8 @@ public abstract class VaadinService implements Serializable {
private ClassLoader classLoader;
+ private final Iterable<RequestHandler> requestHandlers;
+
/**
* Creates a new vaadin service based on a deployment configuration
*
@@ -108,6 +120,33 @@ public abstract class VaadinService implements Serializable {
+ classLoaderName, e);
}
}
+
+ List<RequestHandler> handlers = createRequestHandlers();
+ Collections.reverse(handlers);
+ requestHandlers = Collections.unmodifiableCollection(handlers);
+
+ }
+
+ /**
+ * Called during initialization to add the request handlers for the service.
+ * Note that the returned list will be reversed so the last handler will be
+ * called first. This enables overriding this method and using add on the
+ * returned list to add a custom request handler which overrides any
+ * predefined handler.
+ *
+ * @return The list of request handlers used by this service.
+ */
+ protected List<RequestHandler> createRequestHandlers() {
+ ArrayList<RequestHandler> handlers = new ArrayList<RequestHandler>();
+ handlers.add(new SessionRequestHandler());
+ handlers.add(new PublishedFileHandler());
+ handlers.add(new HeartbeatHandler());
+ handlers.add(new FileUploadHandler());
+ handlers.add(new UidlRequestHandler(this));
+ handlers.add(new UnsupportedBrowserHandler());
+ handlers.add(new ConnectorResourceHandler());
+
+ return handlers;
}
/**
@@ -286,13 +325,6 @@ public abstract class VaadinService implements Serializable {
public abstract File getBaseDirectory();
/**
- * Creates the bootstrap handler that should be used to generate the initial
- * HTML bootstrapping a new {@link UI} in the given session.
- */
- protected abstract BootstrapHandler createBootstrapHandler(
- VaadinSession session);
-
- /**
* Adds a listener that gets notified when a new Vaadin service session is
* initialized for this service.
* <p>
@@ -1203,4 +1235,125 @@ public abstract class VaadinService implements Serializable {
}
CurrentInstance.clearAll();
}
+
+ /**
+ * Returns the request handlers that are registered with this service. The
+ * iteration order of the returned collection is the same as the order in
+ * which the request handlers will be invoked when a request is handled.
+ *
+ * @return a collection of request handlers in the order they are invoked
+ *
+ * @see #createRequestHandlers()
+ *
+ * @since 7.1
+ */
+ public Iterable<RequestHandler> getRequestHandlers() {
+ return requestHandlers;
+ }
+
+ /**
+ * Handles the incoming request and writes the response into the response
+ * object. Uses {@link #getRequestHandlers()} for handling the request.
+ *
+ * @param request
+ * The incoming request
+ * @param response
+ * The outgoing response
+ * @throws ServiceException
+ * Any exception that occurs during response handling will be
+ * wrapped in a ServiceException
+ */
+ public void handleRequest(VaadinRequest request, VaadinResponse response)
+ throws ServiceException {
+ requestStart(request, response);
+
+ VaadinSession vaadinSession = null;
+ try {
+ // Find out the service session this request is related to
+ vaadinSession = findVaadinSession(request);
+ if (vaadinSession == null) {
+ return;
+ }
+
+ for (RequestHandler handler : getRequestHandlers()) {
+ if (handler.handleRequest(vaadinSession, request, response)) {
+ return;
+ }
+ }
+
+ // Request not handled by any RequestHandler
+ response.sendError(HttpServletResponse.SC_NOT_FOUND,
+ "Request was not handled by any registered handler.");
+
+ } catch (final SessionExpiredException e) {
+ handleSessionExpired(request, response);
+ } catch (final Throwable e) {
+ handleExceptionDuringRequest(request, response, vaadinSession, e);
+ } finally {
+ requestEnd(request, response, vaadinSession);
+ }
+ }
+
+ private void handleExceptionDuringRequest(VaadinRequest request,
+ VaadinResponse response, VaadinSession vaadinSession, Throwable t)
+ throws ServiceException {
+ if (vaadinSession != null) {
+ vaadinSession.lock();
+ }
+ try {
+ ErrorHandler errorHandler = ErrorEvent
+ .findErrorHandler(vaadinSession);
+
+ // if this was an UIDL request, response UIDL back to client
+ if (ServletPortletHelper.isUIDLRequest(request)) {
+ SystemMessages ci = getSystemMessages(
+ ServletPortletHelper.findLocale(null, vaadinSession,
+ request), request);
+ try {
+ criticalNotification(request, response,
+ ci.getInternalErrorCaption(),
+ ci.getInternalErrorMessage(), null,
+ ci.getInternalErrorURL());
+ } catch (IOException e) {
+ // An exception occured while writing the response. Log
+ // it and continue handling only the original error.
+ getLogger()
+ .log(Level.WARNING,
+ "Failed to write critical notification response to the client",
+ e);
+ }
+ if (errorHandler != null) {
+ errorHandler.error(new ErrorEvent(t));
+ }
+ } else {
+ if (errorHandler != null) {
+ errorHandler.error(new ErrorEvent(t));
+ }
+
+ // Re-throw other exceptions
+ throw new ServiceException(t);
+ }
+ } finally {
+ if (vaadinSession != null) {
+ vaadinSession.unlock();
+ }
+ }
+
+ }
+
+ /**
+ * Called when the session has expired and the request handling is therefore
+ * aborted.
+ *
+ * @param request
+ * The request
+ * @param response
+ * The response
+ * @throws ServiceException
+ * Thrown if there was any problem handling the expiration of
+ * the session
+ */
+ protected abstract void handleSessionExpired(VaadinRequest request,
+ VaadinResponse response) throws ServiceException;
+
}
diff --git a/server/src/com/vaadin/server/VaadinServlet.java b/server/src/com/vaadin/server/VaadinServlet.java
index 5780b2bbc9..2c274957d9 100644
--- a/server/src/com/vaadin/server/VaadinServlet.java
+++ b/server/src/com/vaadin/server/VaadinServlet.java
@@ -39,41 +39,12 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.vaadin.sass.internal.ScssStylesheet;
-import com.vaadin.server.LegacyCommunicationManager.Callback;
-import com.vaadin.server.communication.FileUploadHandler;
-import com.vaadin.server.communication.HeartbeatHandler;
-import com.vaadin.server.communication.PublishedFileHandler;
-import com.vaadin.server.communication.SessionRequestHandler;
-import com.vaadin.server.communication.UIInitHandler;
-import com.vaadin.server.communication.UidlRequestHandler;
+import com.vaadin.server.communication.ServletUIInitHandler;
import com.vaadin.util.CurrentInstance;
@SuppressWarnings("serial")
public class VaadinServlet extends HttpServlet implements Constants {
- private static class AbstractApplicationServletWrapper implements Callback {
-
- private final VaadinServlet servlet;
-
- public AbstractApplicationServletWrapper(VaadinServlet servlet) {
- this.servlet = servlet;
- }
-
- @Override
- public void criticalNotification(VaadinRequest request,
- VaadinResponse response, String cap, String msg,
- String details, String outOfSyncURL) throws IOException {
- servlet.criticalNotification((VaadinServletRequest) request,
- ((VaadinServletResponse) 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 VaadinServletService servletService;
/**
@@ -200,7 +171,23 @@ public class VaadinServlet extends HttpServlet implements Constants {
}
CurrentInstance.clearAll();
setCurrent(this);
- service(createVaadinRequest(request), createVaadinResponse(response));
+
+ VaadinServletRequest vaadinRequest = createVaadinRequest(request);
+ VaadinServletResponse vaadinResponse = createVaadinResponse(response);
+ if (!ensureCookiesEnabled(vaadinRequest, vaadinResponse)) {
+ return;
+ }
+
+ if (isStaticResourceRequest(request)) {
+ serveStaticResources(request, response);
+ return;
+ }
+ try {
+ getService().handleRequest(vaadinRequest, vaadinResponse);
+ } catch (ServiceException e) {
+ throw new ServletException(e);
+ }
+
}
/**
@@ -239,73 +226,6 @@ public class VaadinServlet extends HttpServlet implements Constants {
}
}
- private void service(VaadinServletRequest request,
- VaadinServletResponse response) throws ServletException,
- IOException {
- getService().requestStart(request, response);
- VaadinSession vaadinSession = null;
-
- try {
- AbstractApplicationServletWrapper servletWrapper = new AbstractApplicationServletWrapper(
- this);
-
- RequestType requestType = getRequestType(request);
- if (!ensureCookiesEnabled(requestType, request, response)) {
- return;
- }
-
- if (requestType == RequestType.STATIC_FILE) {
- serveStaticResources(request, response);
- return;
- }
-
- try {
- // Find out the service session this request is related to
- vaadinSession = getService().findVaadinSession(request);
- if (vaadinSession == null) {
- return;
- }
-
- if (requestType == RequestType.PUBLISHED_FILE) {
- new PublishedFileHandler().handleRequest(vaadinSession,
- request, response);
- return;
- } else if (requestType == RequestType.HEARTBEAT) {
- new HeartbeatHandler().handleRequest(vaadinSession,
- request, response);
- return;
- } else if (requestType == RequestType.FILE_UPLOAD) {
- new FileUploadHandler().handleRequest(vaadinSession,
- request, response);
- return;
- } else if (requestType == RequestType.UIDL) {
- new UidlRequestHandler(servletWrapper).handleRequest(
- vaadinSession, request, response);
- return;
- } else if (requestType == RequestType.BROWSER_DETAILS) {
- // Browser details - not related to a specific UI
- new UIInitHandler().handleRequest(vaadinSession, request,
- response);
- return;
- } else if (new SessionRequestHandler().handleRequest(
- vaadinSession, request, response)) {
- return;
- }
-
- // Request not handled by any RequestHandler -> 404
- response.sendError(HttpServletResponse.SC_NOT_FOUND);
-
- } catch (final SessionExpiredException e) {
- // Session has expired, notify user
- handleServiceSessionExpired(request, response);
- } catch (final Throwable e) {
- handleServiceException(request, response, vaadinSession, e);
- }
- } finally {
- getService().requestEnd(request, response, vaadinSession);
- }
- }
-
private VaadinServletResponse createVaadinResponse(
HttpServletResponse response) {
return new VaadinServletResponse(response, getService());
@@ -347,10 +267,9 @@ public class VaadinServlet extends HttpServlet implements Constants {
* @return false if cookies are disabled, true otherwise
* @throws IOException
*/
- private boolean ensureCookiesEnabled(RequestType requestType,
- VaadinServletRequest request, VaadinServletResponse response)
- throws IOException {
- if (requestType == RequestType.UIDL) {
+ private boolean ensureCookiesEnabled(VaadinServletRequest request,
+ VaadinServletResponse response) throws IOException {
+ if (ServletPortletHelper.isUIDLRequest(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
@@ -509,44 +428,6 @@ public class VaadinServlet extends HttpServlet implements Constants {
return resultPath;
}
- private void handleServiceException(VaadinServletRequest request,
- VaadinServletResponse response, VaadinSession vaadinSession,
- Throwable e) throws IOException, ServletException {
- if (vaadinSession != null) {
- vaadinSession.lock();
- }
- try {
- ErrorHandler errorHandler = ErrorEvent
- .findErrorHandler(vaadinSession);
-
- // if this was an UIDL request, response UIDL back to client
- if (getRequestType(request) == RequestType.UIDL) {
- SystemMessages ci = getService().getSystemMessages(
- ServletPortletHelper.findLocale(null, vaadinSession,
- request), request);
- criticalNotification(request, response,
- ci.getInternalErrorCaption(),
- ci.getInternalErrorMessage(), null,
- ci.getInternalErrorURL());
- if (errorHandler != null) {
- errorHandler.error(new ErrorEvent(e));
- }
- } else {
- if (errorHandler != null) {
- errorHandler.error(new ErrorEvent(e));
- }
-
- // Re-throw other exceptions
- throw new ServletException(e);
- }
- } finally {
- if (vaadinSession != null) {
- vaadinSession.unlock();
- }
- }
-
- }
-
/**
* A helper method to strip away characters that might somehow be used for
* XSS attacs. Leaves at least alphanumeric characters intact. Also removes
@@ -591,68 +472,6 @@ public class VaadinServlet extends HttpServlet implements Constants {
return DEFAULT_THEME_NAME;
}
- /**
- * @param request
- * @param response
- * @throws IOException
- * @throws ServletException
- *
- * @deprecated As of 7.0. Will likely change or be removed in a future
- * version
- */
- @Deprecated
- void handleServiceSessionExpired(VaadinServletRequest request,
- VaadinServletResponse response) throws IOException,
- ServletException {
-
- try {
- SystemMessages ci = getService().getSystemMessages(
- ServletPortletHelper.findLocale(null, null, request),
- request);
- RequestType requestType = getRequestType(request);
- if (requestType == RequestType.UIDL) {
- /*
- * 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());
-
- } else if (requestType == RequestType.HEARTBEAT) {
- response.sendError(HttpServletResponse.SC_GONE,
- "Session expired");
- } else {
- // 'plain' http req - e.g. browser reload;
- // just go ahead redirect the browser
- String sessionExpiredURL = ci.getSessionExpiredURL();
- if (sessionExpiredURL != null) {
- response.sendRedirect(sessionExpiredURL);
- } else {
- /*
- * Session expired as a result of a standard http request
- * and we have nowhere to redirect. Reloading would likely
- * cause an endless loop. This can at least happen if
- * refreshing a resource when the session has expired.
- */
- response.sendError(HttpServletResponse.SC_GONE,
- "Session expired");
- }
- }
- } catch (SystemMessageException ee) {
- throw new ServletException(ee);
- }
-
- }
-
private void handleServiceSecurityException(VaadinServletRequest request,
VaadinServletResponse response) throws IOException,
ServletException {
@@ -664,14 +483,13 @@ public class VaadinServlet extends HttpServlet implements Constants {
*/
SystemMessages ci = getService().getSystemMessages(
request.getLocale(), request);
- RequestType requestType = getRequestType(request);
- if (requestType == RequestType.UIDL) {
+ if (ServletPortletHelper.isUIDLRequest(request)) {
// send uidl redirect
criticalNotification(request, response,
ci.getCommunicationErrorCaption(),
ci.getCommunicationErrorMessage(),
INVALID_SECURITY_KEY_MSG, ci.getCommunicationErrorURL());
- } else if (requestType == RequestType.HEARTBEAT) {
+ } else if (ServletPortletHelper.isHeartbeatRequest(request)) {
response.sendError(HttpServletResponse.SC_FORBIDDEN,
"Forbidden");
} else {
@@ -1056,10 +874,12 @@ public class VaadinServlet extends HttpServlet implements Constants {
/**
*
* @author Vaadin Ltd
- * @since 7.0.0
+ * @since 7.0
*
- * @deprecated As of 7.0. Will likely change or be removed in a future
- * version
+ * @deprecated As of 7.0. This is no longer used and only provided for
+ * backwards compatibility. Each {@link RequestHandler} can
+ * individually decide whether it wants to handle a request or
+ * not.
*/
@Deprecated
protected enum RequestType {
@@ -1070,8 +890,10 @@ public class VaadinServlet extends HttpServlet implements Constants {
* @param request
* @return
*
- * @deprecated As of 7.0. Will likely change or be removed in a future
- * version
+ * @deprecated As of 7.0. This is no longer used and only provided for
+ * backwards compatibility. Each {@link RequestHandler} can
+ * individually decide whether it wants to handle a request or
+ * not.
*/
@Deprecated
protected RequestType getRequestType(VaadinServletRequest request) {
@@ -1079,7 +901,7 @@ public class VaadinServlet extends HttpServlet implements Constants {
return RequestType.FILE_UPLOAD;
} else if (ServletPortletHelper.isPublishedFileRequest(request)) {
return RequestType.PUBLISHED_FILE;
- } else if (isBrowserDetailsRequest(request)) {
+ } else if (ServletUIInitHandler.isUIInitRequest(request)) {
return RequestType.BROWSER_DETAILS;
} else if (ServletPortletHelper.isUIDLRequest(request)) {
return RequestType.UIDL;
@@ -1094,12 +916,7 @@ public class VaadinServlet extends HttpServlet implements Constants {
}
- private static boolean isBrowserDetailsRequest(HttpServletRequest request) {
- return "POST".equals(request.getMethod())
- && request.getParameter("v-browserDetails") != null;
- }
-
- private boolean isStaticResourceRequest(HttpServletRequest request) {
+ protected boolean isStaticResourceRequest(HttpServletRequest request) {
String pathInfo = request.getPathInfo();
if (pathInfo == null || pathInfo.length() <= 10) {
return false;
@@ -1235,4 +1052,5 @@ public class VaadinServlet extends HttpServlet implements Constants {
private static final Logger getLogger() {
return Logger.getLogger(VaadinServlet.class.getName());
}
+
}
diff --git a/server/src/com/vaadin/server/VaadinServletService.java b/server/src/com/vaadin/server/VaadinServletService.java
index f453a6b140..a12e2b47e2 100644
--- a/server/src/com/vaadin/server/VaadinServletService.java
+++ b/server/src/com/vaadin/server/VaadinServletService.java
@@ -17,15 +17,19 @@
package com.vaadin.server;
import java.io.File;
+import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
+import java.util.List;
+import java.util.logging.Logger;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
-import com.vaadin.server.VaadinServlet.RequestType;
import com.vaadin.server.communication.ServletBootstrapHandler;
+import com.vaadin.server.communication.ServletUIInitHandler;
import com.vaadin.ui.UI;
public class VaadinServletService extends VaadinService {
@@ -47,6 +51,31 @@ public class VaadinServletService extends VaadinService {
}
}
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.vaadin.server.LegacyCommunicationManager.Callback#criticalNotification
+ * (com.vaadin.server.VaadinRequest, com.vaadin.server.VaadinResponse,
+ * java.lang.String, java.lang.String, java.lang.String, java.lang.String)
+ */
+ @Deprecated
+ @Override
+ public void criticalNotification(VaadinRequest request,
+ VaadinResponse response, String cap, String msg, String details,
+ String url) throws IOException {
+ getServlet().criticalNotification((VaadinServletRequest) request,
+ (VaadinServletResponse) response, cap, msg, details, url);
+ }
+
+ @Override
+ protected List<RequestHandler> createRequestHandlers() {
+ List<RequestHandler> handlers = super.createRequestHandlers();
+ handlers.add(0, new ServletBootstrapHandler());
+ handlers.add(new ServletUIInitHandler());
+ return handlers;
+ }
+
/**
* Retrieves a reference to the servlet associated with this service.
*
@@ -135,12 +164,11 @@ public class VaadinServletService extends VaadinService {
@Override
protected boolean requestCanCreateSession(VaadinRequest request) {
- RequestType requestType = getRequestType(request);
- if (requestType == RequestType.BROWSER_DETAILS) {
+ if (ServletUIInitHandler.isUIInitRequest(request)) {
// This is the first request if you are embedding by writing the
// embedding code yourself
return true;
- } else if (requestType == RequestType.OTHER) {
+ } else if (isOtherRequest(request)) {
/*
* I.e URIs that are not RPC calls or static (theme) files.
*/
@@ -150,25 +178,15 @@ public class VaadinServletService extends VaadinService {
return false;
}
- /**
- * Gets the request type for the request.
- *
- * @param request
- * the request to get a request type for
- * @return the request type
- *
- * @deprecated As of 7.0. Will likely change or be removed in a future
- * version
- */
- @Deprecated
- protected RequestType getRequestType(VaadinRequest request) {
- RequestType type = (RequestType) request.getAttribute(RequestType.class
- .getName());
- if (type == null) {
- type = getServlet().getRequestType((VaadinServletRequest) request);
- request.setAttribute(RequestType.class.getName(), type);
- }
- return type;
+ private boolean isOtherRequest(VaadinRequest request) {
+ // TODO This should be refactored in some way. It should not be
+ // necessary to check all these types.
+ return (!ServletPortletHelper.isAppRequest(request)
+ && !ServletUIInitHandler.isUIInitRequest(request)
+ && !ServletPortletHelper.isFileUploadRequest(request)
+ && !ServletPortletHelper.isHeartbeatRequest(request)
+ && !ServletPortletHelper.isPublishedFileRequest(request) && !ServletPortletHelper
+ .isUIDLRequest(request));
}
@Override
@@ -235,8 +253,73 @@ public class VaadinServletService extends VaadinService {
return appId;
}
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.vaadin.server.VaadinService#handleSessionExpired(com.vaadin.server
+ * .VaadinRequest, com.vaadin.server.VaadinResponse)
+ */
@Override
- protected BootstrapHandler createBootstrapHandler(VaadinSession session) {
- return new ServletBootstrapHandler();
+ protected void handleSessionExpired(VaadinRequest request,
+ VaadinResponse response) throws ServiceException {
+ if (!(request instanceof VaadinServletRequest)) {
+ throw new ServiceException(new IllegalArgumentException(
+ "handleSessionExpired called with a non-VaadinServletRequest: "
+ + request.getClass().getName()));
+ }
+
+ VaadinServletRequest servletRequest = (VaadinServletRequest) request;
+ VaadinServletResponse servletResponse = (VaadinServletResponse) response;
+
+ try {
+ SystemMessages ci = getSystemMessages(
+ ServletPortletHelper.findLocale(null, null, request),
+ request);
+ if (ServletPortletHelper.isUIDLRequest(request)) {
+ /*
+ * Invalidate session (weird to have session if we're saying
+ * that it's expired)
+ *
+ * Session must be invalidated before criticalNotification as it
+ * commits the response.
+ */
+ servletRequest.getSession().invalidate();
+
+ // send uidl redirect
+ criticalNotification(request, response,
+ ci.getSessionExpiredCaption(),
+ ci.getSessionExpiredMessage(), null,
+ ci.getSessionExpiredURL());
+
+ } else if (ServletPortletHelper.isHeartbeatRequest(request)) {
+ response.sendError(HttpServletResponse.SC_GONE,
+ "Session expired");
+ } else {
+ // 'plain' http req - e.g. browser reload;
+ // just go ahead redirect the browser
+ String sessionExpiredURL = ci.getSessionExpiredURL();
+ if (sessionExpiredURL != null) {
+ servletResponse.sendRedirect(sessionExpiredURL);
+ } else {
+ /*
+ * Session expired as a result of a standard http request
+ * and we have nowhere to redirect. Reloading would likely
+ * cause an endless loop. This can at least happen if
+ * refreshing a resource when the session has expired.
+ */
+ response.sendError(HttpServletResponse.SC_GONE,
+ "Session expired");
+ }
+ }
+ } catch (IOException e) {
+ throw new ServiceException(e);
+ }
+
}
+
+ private static final Logger getLogger() {
+ return Logger.getLogger(VaadinServletService.class.getName());
+ }
+
}
diff --git a/server/src/com/vaadin/server/communication/FileUploadHandler.java b/server/src/com/vaadin/server/communication/FileUploadHandler.java
index fc3c4b65f8..1f5011a42e 100644
--- a/server/src/com/vaadin/server/communication/FileUploadHandler.java
+++ b/server/src/com/vaadin/server/communication/FileUploadHandler.java
@@ -217,6 +217,9 @@ public class FileUploadHandler implements RequestHandler {
@Override
public boolean handleRequest(VaadinSession session, VaadinRequest request,
VaadinResponse response) throws IOException {
+ if (!ServletPortletHelper.isFileUploadRequest(request)) {
+ return false;
+ }
/*
* URI pattern: APP/UPLOAD/[UIID]/[PID]/[NAME]/[SECKEY] See
diff --git a/server/src/com/vaadin/server/communication/HeartbeatHandler.java b/server/src/com/vaadin/server/communication/HeartbeatHandler.java
index a696ad3919..a547d32b30 100644
--- a/server/src/com/vaadin/server/communication/HeartbeatHandler.java
+++ b/server/src/com/vaadin/server/communication/HeartbeatHandler.java
@@ -20,10 +20,12 @@ import java.io.IOException;
import javax.servlet.http.HttpServletResponse;
+import com.vaadin.server.ServletPortletHelper;
import com.vaadin.server.SynchronizedRequestHandler;
import com.vaadin.server.VaadinRequest;
import com.vaadin.server.VaadinResponse;
import com.vaadin.server.VaadinSession;
+import com.vaadin.shared.ui.ui.UIConstants;
import com.vaadin.ui.UI;
/**
@@ -49,6 +51,10 @@ public class HeartbeatHandler extends SynchronizedRequestHandler {
@Override
public boolean synchronizedHandleRequest(VaadinSession session,
VaadinRequest request, VaadinResponse response) throws IOException {
+ if (!ServletPortletHelper.isHeartbeatRequest(request)) {
+ return false;
+ }
+
UI ui = session.getService().findUI(request);
if (ui != null) {
ui.setLastHeartbeatTimestamp(System.currentTimeMillis());
diff --git a/server/src/com/vaadin/server/communication/PortletDummyRequestHandler.java b/server/src/com/vaadin/server/communication/PortletDummyRequestHandler.java
new file mode 100644
index 0000000000..8383cf607b
--- /dev/null
+++ b/server/src/com/vaadin/server/communication/PortletDummyRequestHandler.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2000-2013 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.server.communication;
+
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+
+import javax.portlet.PortletResponse;
+import javax.portlet.ResourceRequest;
+import javax.portlet.ResourceResponse;
+
+import com.vaadin.server.RequestHandler;
+import com.vaadin.server.VaadinPortletResponse;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.server.VaadinResponse;
+import com.vaadin.server.VaadinSession;
+
+/**
+ * Request handler which provides a dummy HTML response to any resource request
+ * with the resource id DUMMY.
+ *
+ * @author Vaadin Ltd
+ * @since 7.1
+ */
+public class PortletDummyRequestHandler implements RequestHandler {
+
+ @Override
+ public boolean handleRequest(VaadinSession session, VaadinRequest request,
+ VaadinResponse response) throws IOException {
+ if (!isDummyRequest(request)) {
+ return false;
+ }
+
+ /*
+ * 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.
+ */
+ PortletResponse portletResponse = ((VaadinPortletResponse) response)
+ .getPortletResponse();
+ if (portletResponse instanceof ResourceResponse) {
+ ((ResourceResponse) portletResponse).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();
+
+ return true;
+ }
+
+ public static boolean isDummyRequest(VaadinRequest request) {
+ ResourceRequest resourceRequest = PortletUIInitHandler
+ .getResourceRequest(request);
+ if (resourceRequest == null) {
+ return false;
+ }
+
+ return resourceRequest.getResourceID() != null
+ && resourceRequest.getResourceID().equals("DUMMY");
+ }
+
+}
diff --git a/server/src/com/vaadin/server/communication/PortletUIInitHandler.java b/server/src/com/vaadin/server/communication/PortletUIInitHandler.java
new file mode 100644
index 0000000000..d5d1e6b98d
--- /dev/null
+++ b/server/src/com/vaadin/server/communication/PortletUIInitHandler.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2000-2013 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.server.communication;
+
+import javax.portlet.PortletRequest;
+import javax.portlet.ResourceRequest;
+
+import com.vaadin.server.VaadinPortletRequest;
+import com.vaadin.server.VaadinRequest;
+
+public class PortletUIInitHandler extends UIInitHandler {
+
+ @Override
+ protected boolean isInitRequest(VaadinRequest request) {
+ return isUIInitRequest(request);
+ }
+
+ public static boolean isUIInitRequest(VaadinRequest request) {
+ ResourceRequest resourceRequest = getResourceRequest(request);
+ if (resourceRequest == null) {
+ return false;
+ }
+
+ return UIInitHandler.BROWSER_DETAILS_PARAMETER.equals(resourceRequest
+ .getResourceID());
+ }
+
+ /**
+ * Returns the {@link ResourceRequest} for the given request or null if none
+ * could be found.
+ *
+ * @param request
+ * The original request, must be a {@link VaadinPortletRequest}
+ * @return The resource request from the request parameter or null
+ */
+ static ResourceRequest getResourceRequest(VaadinRequest request) {
+ if (!(request instanceof VaadinPortletRequest)) {
+ throw new IllegalArgumentException(
+ "Request must a VaadinPortletRequest");
+ }
+ PortletRequest portletRequest = ((VaadinPortletRequest) request)
+ .getPortletRequest();
+ if (!(portletRequest instanceof ResourceRequest)) {
+ return null;
+ }
+
+ return (ResourceRequest) portletRequest;
+
+ }
+}
diff --git a/server/src/com/vaadin/server/communication/PublishedFileHandler.java b/server/src/com/vaadin/server/communication/PublishedFileHandler.java
index 1cd70bb173..8fe0f7085f 100644
--- a/server/src/com/vaadin/server/communication/PublishedFileHandler.java
+++ b/server/src/com/vaadin/server/communication/PublishedFileHandler.java
@@ -28,6 +28,7 @@ import com.vaadin.annotations.StyleSheet;
import com.vaadin.server.Constants;
import com.vaadin.server.LegacyCommunicationManager;
import com.vaadin.server.RequestHandler;
+import com.vaadin.server.ServletPortletHelper;
import com.vaadin.server.VaadinRequest;
import com.vaadin.server.VaadinResponse;
import com.vaadin.server.VaadinSession;
@@ -55,6 +56,9 @@ public class PublishedFileHandler implements RequestHandler {
@Override
public boolean handleRequest(VaadinSession session, VaadinRequest request,
VaadinResponse response) throws IOException {
+ if (!ServletPortletHelper.isPublishedFileRequest(request)) {
+ return false;
+ }
String pathInfo = request.getPathInfo();
// + 2 to also remove beginning and ending slashes
diff --git a/server/src/com/vaadin/server/communication/ServletUIInitHandler.java b/server/src/com/vaadin/server/communication/ServletUIInitHandler.java
new file mode 100644
index 0000000000..6286c161f2
--- /dev/null
+++ b/server/src/com/vaadin/server/communication/ServletUIInitHandler.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2000-2013 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.server.communication;
+
+import com.vaadin.server.VaadinRequest;
+
+public class ServletUIInitHandler extends UIInitHandler {
+
+ @Override
+ protected boolean isInitRequest(VaadinRequest request) {
+ return isUIInitRequest(request);
+ }
+
+ public static boolean isUIInitRequest(VaadinRequest request) {
+ return "POST".equals(request.getMethod())
+ && request
+ .getParameter(UIInitHandler.BROWSER_DETAILS_PARAMETER) != null;
+ }
+
+}
diff --git a/server/src/com/vaadin/server/communication/SessionRequestHandler.java b/server/src/com/vaadin/server/communication/SessionRequestHandler.java
index 244cb0121d..14c940acf5 100644
--- a/server/src/com/vaadin/server/communication/SessionRequestHandler.java
+++ b/server/src/com/vaadin/server/communication/SessionRequestHandler.java
@@ -22,6 +22,7 @@ import com.vaadin.server.RequestHandler;
import com.vaadin.server.VaadinRequest;
import com.vaadin.server.VaadinResponse;
import com.vaadin.server.VaadinSession;
+import com.vaadin.shared.ApplicationConstants;
/**
* Handles a request by passing it to each registered {@link RequestHandler} in
@@ -50,6 +51,13 @@ public class SessionRequestHandler implements RequestHandler {
@Override
public boolean handleRequest(VaadinSession session, VaadinRequest request,
VaadinResponse response) throws IOException {
+ String pathInfo = request.getPathInfo();
+ if (pathInfo.startsWith("/" + ApplicationConstants.APP_PATH + "/")) {
+ // /<APP_PATH>/ is reserved for Vaadin internal use and these
+ // requests should not be passed to session request handlers
+ return false;
+ }
+
// Use a copy to avoid ConcurrentModificationException
session.lock();
ArrayList<RequestHandler> requestHandlers;
diff --git a/server/src/com/vaadin/server/communication/UIInitHandler.java b/server/src/com/vaadin/server/communication/UIInitHandler.java
index e4790e95e5..0e18209986 100644
--- a/server/src/com/vaadin/server/communication/UIInitHandler.java
+++ b/server/src/com/vaadin/server/communication/UIInitHandler.java
@@ -49,11 +49,18 @@ import com.vaadin.ui.UI;
* @author Vaadin Ltd
* @since 7.1
*/
-public class UIInitHandler extends SynchronizedRequestHandler {
+public abstract class UIInitHandler extends SynchronizedRequestHandler {
+
+ public static final String BROWSER_DETAILS_PARAMETER = "v-browserDetails";
+
+ protected abstract boolean isInitRequest(VaadinRequest request);
@Override
public boolean synchronizedHandleRequest(VaadinSession session,
VaadinRequest request, VaadinResponse response) throws IOException {
+ if (!isInitRequest(request)) {
+ return false;
+ }
// NOTE! GateIn requires, for some weird reason, getOutputStream
// to be used instead of getWriter() (it seems to interpret
diff --git a/server/src/com/vaadin/server/communication/UidlRequestHandler.java b/server/src/com/vaadin/server/communication/UidlRequestHandler.java
index e55f39246e..e626bbe58d 100644
--- a/server/src/com/vaadin/server/communication/UidlRequestHandler.java
+++ b/server/src/com/vaadin/server/communication/UidlRequestHandler.java
@@ -32,6 +32,7 @@ import com.vaadin.server.Constants;
import com.vaadin.server.LegacyCommunicationManager;
import com.vaadin.server.LegacyCommunicationManager.Callback;
import com.vaadin.server.LegacyCommunicationManager.InvalidUIDLSecurityKeyException;
+import com.vaadin.server.ServletPortletHelper;
import com.vaadin.server.SynchronizedRequestHandler;
import com.vaadin.server.VaadinRequest;
import com.vaadin.server.VaadinResponse;
@@ -53,6 +54,8 @@ import com.vaadin.ui.UI;
*/
public class UidlRequestHandler extends SynchronizedRequestHandler {
+ public static final String UIDL_PATH = "UIDL/";
+
private Callback criticalNotifier;
private ServerRpcHandler rpcHandler = new ServerRpcHandler();
@@ -64,7 +67,9 @@ public class UidlRequestHandler extends SynchronizedRequestHandler {
@Override
public boolean synchronizedHandleRequest(VaadinSession session,
VaadinRequest request, VaadinResponse response) throws IOException {
-
+ if (!ServletPortletHelper.isUIDLRequest(request)) {
+ return false;
+ }
UI uI = session.getService().findUI(request);
checkWidgetsetVersion(request);