WebUrl url = request.getUrl();
RequestFlavor flavor = request.getFlavor();
Mode processingMode = Mode.Default;
// Try to get hold of an action pool
ActionPool pool = null;
pool = getActionForUrl(url, flavor);
if (pool == null) {
logger.debug("No action found to handle {}", url);
return false;
}
// Match! Let's try to get an actual action from that pool
Action action = null;
try {
action = (Action) pool.borrowObject();
} catch (Throwable t) {
logger.error("Error getting action from action pool", t);
DispatchUtils.sendInternalError(request, response);
return true;
}
// Make sure the action is returned to the pool no matter what
try {
// Check the request method. We won't handle just everything
String requestMethod = request.getMethod().toUpperCase();
if (!action.supportsMethod(requestMethod)) {
if ("OPTIONS".equals(requestMethod)) {
StringBuffer verbs = new StringBuffer();
for (String verb : action.getMethods()) {
if (verbs.length() > 0)
verbs.append(",");
verbs.append(verb);
}
logger.trace("Answering options request to {} with {}", action, verbs.toString());
response.setHeader("Allow", verbs.toString());
response.setContentLength(0);
return true;
} else {
logger.debug("Action {} does not support {} requests", action, requestMethod);
DispatchUtils.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, request, response);
return true;
}
}
// Check for explicit no cache instructions
boolean noCache = request.getParameter(ResponseCache.NOCACHE_PARAM) != null;
// Check if the page is already part of the cache. If so, our task is
// already done!
if (!noCache && request.getVersion() == Resource.LIVE) {
long expirationTime = action.getCacheExpirationTime();
long revalidationTime = action.getClientRevalidationTime();
// Create the set of tags that identify the request output
CacheTagSet cacheTags = createCacheTags(request, action);
// Check if the page is already part of the cache
if (response.startResponse(cacheTags.getTags(), expirationTime, revalidationTime)) {
logger.debug("Action answered request for {} from cache", request.getUrl());
return true;
}
processingMode = Mode.Cached;
} else if (Http11Constants.METHOD_HEAD.equals(request.getMethod())) {
// handle HEAD requests
Http11Utils.startHeadResponse(response);
processingMode = Mode.Head;
} else if (request.getVersion() == Resource.WORK) {
response.setCacheExpirationTime(0);
}
logger.debug("Action {} will handle {}", action, url);
// Call the service method depending on the flavor
switch (flavor) {
case HTML:
if (!action.supportsFlavor(flavor) && !(action instanceof HTMLAction))
return false;
serveHTML(action, request, response);
break;
case XML:
if (!action.supportsFlavor(flavor) && !(action instanceof XMLAction))
return false;
serveXML(action, request, response);
break;
case JSON:
if (!action.supportsFlavor(flavor) && !(action instanceof JSONAction))
return false;
serveJSON(action, request, response);
break;
default:
if (action.supportsFlavor(RequestFlavor.HTML) || action instanceof HTMLAction)
serveHTML(action, request, response);
else if (action.supportsFlavor(RequestFlavor.XML) || action instanceof XMLAction)
serveXML(action, request, response);
else if (action.supportsFlavor(RequestFlavor.JSON) || action instanceof JSONAction)
serveJSON(action, request, response);
else
serveGeneric(action, request, response);
}
} finally {
// Finish cache handling
switch (processingMode) {
case Cached:
response.endResponse();
break;
case Head:
Http11Utils.endHeadResponse(response);
break;
default:
break;
}
// Return the action handler to the pool
try {
pool.returnObject(action);
} catch (Throwable t) {
logger.error("Error returning action {} to pool: {}", new Object[] {
action,
t.getMessage(),
t });