package org.osforce.spring4me.web.dispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.osforce.spring4me.web.stereotype.Widget;
import org.osforce.spring4me.web.widget.core.HttpWidgetRequest;
import org.osforce.spring4me.web.widget.core.HttpWidgetResponse;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.servlet.HandlerAdapter;
import org.springframework.web.servlet.HandlerExecutionChain;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.ModelAndViewDefiningException;
import org.springframework.web.util.NestedServletException;
import org.springframework.web.util.UrlPathHelper;
import org.springframework.web.util.WebUtils;
/**
*
* @author <a href="mailto:haozhonghu@hotmail.com">gavin</a>
* @since 0.3.0
* @create Jul 13, 2011 - 9:42:29 PM
* <a href="http://www.opensourceforce.org">开源力量</a>
*/
public class DispatcherServlet extends
org.springframework.web.servlet.DispatcherServlet {
private static final long serialVersionUID = -697624535251017814L;
private static final UrlPathHelper urlPathHelper = new UrlPathHelper();
public DispatcherServlet() {
}
@Override
protected void doDispatch(HttpServletRequest request,
HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HttpServletResponse processedResponse = response;
HandlerExecutionChain mappedHandler = null;
int interceptorIndex = -1;
try {
ModelAndView mv;
boolean errorView = false;
try {
processedRequest = checkMultipart(request);
// Determine handler for the current request.
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
noHandlerFound(processedRequest, processedResponse);
return;
}
// Determine handler adapter for the current request.
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// Widget check
processedRequest = checkWidget(request, mappedHandler.getHandler());
processedResponse = checkWidget(response, mappedHandler.getHandler());
// Process last-modified header, if supported by the handler.
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (logger.isDebugEnabled()) {
String requestUri = urlPathHelper.getRequestUri(request);
logger.debug("Last-Modified value for [" + requestUri + "] is: " + lastModified);
}
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
// Apply preHandle methods of registered interceptors.
HandlerInterceptor[] interceptors = mappedHandler.getInterceptors();
if (interceptors != null) {
for (int i = 0; i < interceptors.length; i++) {
HandlerInterceptor interceptor = interceptors[i];
if (!interceptor.preHandle(processedRequest, processedResponse, mappedHandler.getHandler())) {
triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);
return;
}
interceptorIndex = i;
}
}
// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
// Do we need view name translation?
if (mv != null && !mv.hasView()) {
mv.setViewName(getDefaultViewName(request));
}
// Apply postHandle methods of registered interceptors.
if (interceptors != null) {
for (int i = interceptors.length - 1; i >= 0; i--) {
HandlerInterceptor interceptor = interceptors[i];
interceptor.postHandle(processedRequest, processedResponse, mappedHandler.getHandler(), mv);
}
}
}
catch (ModelAndViewDefiningException ex) {
logger.debug("ModelAndViewDefiningException encountered", ex);
mv = ex.getModelAndView();
}
catch (Exception ex) {
Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
mv = processHandlerException(processedRequest, processedResponse, handler, ex);
errorView = (mv != null);
}
// Did the handler return a view to render?
if (mv != null && !mv.wasCleared()) {
render(mv, processedRequest, processedResponse);
if (errorView) {
WebUtils.clearErrorRequestAttributes(request);
}
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() +
"': assuming HandlerAdapter completed request handling");
}
}
// Trigger after-completion for successful outcome.
triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, processedResponse, null);
}
catch (Exception ex) {
// Trigger after-completion for thrown exception.
triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, processedResponse, ex);
throw ex;
}
catch (Error err) {
ServletException ex = new NestedServletException("Handler processing failed", err);
// Trigger after-completion for thrown exception.
triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, processedResponse, ex);
throw ex;
}
finally {
// Clean up any resources used by a multipart request.
if (processedRequest != request) {
cleanupMultipart(processedRequest);
}
}
}
@Override
protected void render(ModelAndView mv, HttpServletRequest request,
HttpServletResponse response) throws Exception {
super.render(mv, request, response);
if(response instanceof HttpWidgetResponse) {
System.out.println(((HttpWidgetResponse) response).getResponseAsString());
}
}
private HttpServletRequest checkWidget(HttpServletRequest request, Object handler) throws Exception {
Widget widget = AnnotationUtils.findAnnotation(handler.getClass(), Widget.class);
if(widget!=null) {
return new HttpWidgetRequest(request);
}
return request;
}
private HttpServletResponse checkWidget(HttpServletResponse response, Object handler) throws Exception {
Widget widget = AnnotationUtils.findAnnotation(handler.getClass(), Widget.class);
if(widget!=null) {
return new HttpWidgetResponse(response);
}
return response;
}
/**
* Trigger afterCompletion callbacks on the mapped HandlerInterceptors.
* Will just invoke afterCompletion for all interceptors whose preHandle invocation
* has successfully completed and returned true.
* @param mappedHandler the mapped HandlerExecutionChain
* @param interceptorIndex index of last interceptor that successfully completed
* @param ex Exception thrown on handler execution, or <code>null</code> if none
* @see HandlerInterceptor#afterCompletion
*/
private void triggerAfterCompletion(HandlerExecutionChain mappedHandler,
int interceptorIndex,
HttpServletRequest request,
HttpServletResponse response,
Exception ex) throws Exception {
// Apply afterCompletion methods of registered interceptors.
if (mappedHandler != null) {
HandlerInterceptor[] interceptors = mappedHandler.getInterceptors();
if (interceptors != null) {
for (int i = interceptorIndex; i >= 0; i--) {
HandlerInterceptor interceptor = interceptors[i];
try {
interceptor.afterCompletion(request, response, mappedHandler.getHandler(), ex);
}
catch (Throwable ex2) {
logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
}
}
}
}
}
}