Переглянути джерело

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
tags/7.1.0.beta1
Artur Signell 11 роки тому
джерело
коміт
3c479dd00b

+ 6
- 0
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();

+ 38
- 48
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,

+ 22
- 18
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);
}
}
}


+ 0
- 8
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());
}


+ 17
- 238
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

+ 58
- 6
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");
}

}

+ 161
- 8
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;
}

/**
@@ -285,13 +324,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.
@@ -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;

}

+ 35
- 217
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());
}

}

+ 108
- 25
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());
}

}

+ 3
- 0
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

+ 6
- 0
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());

+ 82
- 0
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");
}

}

+ 63
- 0
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;

}
}

+ 4
- 0
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

+ 33
- 0
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;
}

}

+ 8
- 0
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;

+ 8
- 1
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

+ 6
- 1
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);

Завантаження…
Відмінити
Зберегти