1 16 17 package org.springframework.web.servlet; 18 19 import java.io.IOException ; 20 import java.util.ArrayList ; 21 import java.util.Collections ; 22 import java.util.Enumeration ; 23 import java.util.HashMap ; 24 import java.util.HashSet ; 25 import java.util.Iterator ; 26 import java.util.List ; 27 import java.util.Locale ; 28 import java.util.Map ; 29 import java.util.Properties ; 30 import java.util.Set ; 31 32 import javax.servlet.ServletException ; 33 import javax.servlet.http.HttpServletRequest ; 34 import javax.servlet.http.HttpServletResponse ; 35 36 import org.apache.commons.logging.Log; 37 import org.apache.commons.logging.LogFactory; 38 39 import org.springframework.beans.BeansException; 40 import org.springframework.beans.factory.BeanFactoryUtils; 41 import org.springframework.beans.factory.BeanInitializationException; 42 import org.springframework.beans.factory.NoSuchBeanDefinitionException; 43 import org.springframework.beans.factory.config.AutowireCapableBeanFactory; 44 import org.springframework.context.i18n.LocaleContext; 45 import org.springframework.context.i18n.LocaleContextHolder; 46 import org.springframework.core.OrderComparator; 47 import org.springframework.core.io.ClassPathResource; 48 import org.springframework.core.io.support.PropertiesLoaderUtils; 49 import org.springframework.ui.context.ThemeSource; 50 import org.springframework.util.ClassUtils; 51 import org.springframework.util.StringUtils; 52 import org.springframework.web.context.request.RequestAttributes; 53 import org.springframework.web.context.request.RequestContextHolder; 54 import org.springframework.web.context.request.ServletRequestAttributes; 55 import org.springframework.web.multipart.MultipartException; 56 import org.springframework.web.multipart.MultipartHttpServletRequest; 57 import org.springframework.web.multipart.MultipartResolver; 58 import org.springframework.web.util.NestedServletException; 59 import org.springframework.web.util.UrlPathHelper; 60 import org.springframework.web.util.WebUtils; 61 62 143 public class DispatcherServlet extends FrameworkServlet { 144 145 148 public static final String MULTIPART_RESOLVER_BEAN_NAME = "multipartResolver"; 149 150 153 public static final String LOCALE_RESOLVER_BEAN_NAME = "localeResolver"; 154 155 158 public static final String THEME_RESOLVER_BEAN_NAME = "themeResolver"; 159 160 165 public static final String HANDLER_MAPPING_BEAN_NAME = "handlerMapping"; 166 167 172 public static final String HANDLER_ADAPTER_BEAN_NAME = "handlerAdapter"; 173 174 179 public static final String HANDLER_EXCEPTION_RESOLVER_BEAN_NAME = "handlerExceptionResolver"; 180 181 185 public static final String REQUEST_TO_VIEW_NAME_TRANSLATOR_BEAN_NAME = "viewNameTranslator"; 186 187 192 public static final String VIEW_RESOLVER_BEAN_NAME = "viewResolver"; 193 194 198 public static final String HANDLER_EXECUTION_CHAIN_ATTRIBUTE = DispatcherServlet.class.getName() + ".HANDLER"; 199 200 205 public static final String WEB_APPLICATION_CONTEXT_ATTRIBUTE = DispatcherServlet.class.getName() + ".CONTEXT"; 206 207 211 public static final String LOCALE_RESOLVER_ATTRIBUTE = DispatcherServlet.class.getName() + ".LOCALE_RESOLVER"; 212 213 217 public static final String THEME_RESOLVER_ATTRIBUTE = DispatcherServlet.class.getName() + ".THEME_RESOLVER"; 218 219 223 public static final String THEME_SOURCE_ATTRIBUTE = DispatcherServlet.class.getName() + ".THEME_SOURCE"; 224 225 226 229 public static final String PAGE_NOT_FOUND_LOG_CATEGORY = "org.springframework.web.servlet.PageNotFound"; 230 231 235 private static final String DEFAULT_STRATEGIES_PATH = "DispatcherServlet.properties"; 236 237 238 241 protected static final Log pageNotFoundLogger = LogFactory.getLog(PAGE_NOT_FOUND_LOG_CATEGORY); 242 243 private static final Properties defaultStrategies; 244 245 static { 246 try { 250 ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, DispatcherServlet.class); 251 defaultStrategies = PropertiesLoaderUtils.loadProperties(resource); 252 } 253 catch (IOException ex) { 254 throw new IllegalStateException ("Could not load 'DispatcherServlet.properties': " + ex.getMessage()); 255 } 256 } 257 258 259 260 private boolean detectAllHandlerMappings = true; 261 262 263 private boolean detectAllHandlerAdapters = true; 264 265 266 private boolean detectAllHandlerExceptionResolvers = true; 267 268 269 private boolean detectAllViewResolvers = true; 270 271 272 private boolean cleanupAfterInclude = true; 273 274 275 private boolean threadContextInheritable = false; 276 277 278 279 private MultipartResolver multipartResolver; 280 281 282 private LocaleResolver localeResolver; 283 284 285 private ThemeResolver themeResolver; 286 287 288 private List handlerMappings; 289 290 291 private List handlerAdapters; 292 293 294 private List handlerExceptionResolvers; 295 296 297 private RequestToViewNameTranslator viewNameTranslator; 298 299 300 private List viewResolvers; 301 302 303 310 public void setDetectAllHandlerMappings(boolean detectAllHandlerMappings) { 311 this.detectAllHandlerMappings = detectAllHandlerMappings; 312 } 313 314 321 public void setDetectAllHandlerAdapters(boolean detectAllHandlerAdapters) { 322 this.detectAllHandlerAdapters = detectAllHandlerAdapters; 323 } 324 325 332 public void setDetectAllHandlerExceptionResolvers(boolean detectAllHandlerExceptionResolvers) { 333 this.detectAllHandlerExceptionResolvers = detectAllHandlerExceptionResolvers; 334 } 335 336 343 public void setDetectAllViewResolvers(boolean detectAllViewResolvers) { 344 this.detectAllViewResolvers = detectAllViewResolvers; 345 } 346 347 360 public void setCleanupAfterInclude(boolean cleanupAfterInclude) { 361 this.cleanupAfterInclude = cleanupAfterInclude; 362 } 363 364 376 public void setThreadContextInheritable(boolean threadContextInheritable) { 377 this.threadContextInheritable = threadContextInheritable; 378 } 379 380 381 387 protected void initFrameworkServlet() throws ServletException , BeansException { 388 initMultipartResolver(); 389 initLocaleResolver(); 390 initThemeResolver(); 391 initHandlerMappings(); 392 initHandlerAdapters(); 393 initHandlerExceptionResolvers(); 394 initRequestToViewNameTranslator(); 395 initViewResolvers(); 396 } 397 398 403 private void initMultipartResolver() { 404 try { 405 this.multipartResolver = (MultipartResolver) 406 getWebApplicationContext().getBean(MULTIPART_RESOLVER_BEAN_NAME, MultipartResolver.class); 407 if (logger.isDebugEnabled()) { 408 logger.debug("Using MultipartResolver [" + this.multipartResolver + "]"); 409 } 410 } 411 catch (NoSuchBeanDefinitionException ex) { 412 this.multipartResolver = null; 414 if (logger.isDebugEnabled()) { 415 logger.debug("Unable to locate MultipartResolver with name '" + MULTIPART_RESOLVER_BEAN_NAME + 416 "': no multipart request handling provided"); 417 } 418 } 419 } 420 421 426 private void initLocaleResolver() { 427 try { 428 this.localeResolver = (LocaleResolver) 429 getWebApplicationContext().getBean(LOCALE_RESOLVER_BEAN_NAME, LocaleResolver.class); 430 if (logger.isDebugEnabled()) { 431 logger.debug("Using LocaleResolver [" + this.localeResolver + "]"); 432 } 433 } 434 catch (NoSuchBeanDefinitionException ex) { 435 this.localeResolver = (LocaleResolver) getDefaultStrategy(LocaleResolver.class); 437 if (logger.isDebugEnabled()) { 438 logger.debug("Unable to locate LocaleResolver with name '" + LOCALE_RESOLVER_BEAN_NAME + 439 "': using default [" + this.localeResolver + "]"); 440 } 441 } 442 } 443 444 449 private void initThemeResolver() { 450 try { 451 this.themeResolver = (ThemeResolver) 452 getWebApplicationContext().getBean(THEME_RESOLVER_BEAN_NAME, ThemeResolver.class); 453 if (logger.isDebugEnabled()) { 454 logger.debug("Using ThemeResolver [" + this.themeResolver + "]"); 455 } 456 } 457 catch (NoSuchBeanDefinitionException ex) { 458 this.themeResolver = (ThemeResolver) getDefaultStrategy(ThemeResolver.class); 460 if (logger.isDebugEnabled()) { 461 logger.debug("Unable to locate ThemeResolver with name '" + THEME_RESOLVER_BEAN_NAME + 462 "': using default [" + this.themeResolver + "]"); 463 } 464 } 465 } 466 467 472 private void initHandlerMappings() { 473 if (this.detectAllHandlerMappings) { 474 Map matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors( 477 getWebApplicationContext(), HandlerMapping.class, true, false); 478 if (!matchingBeans.isEmpty()) { 479 this.handlerMappings = new ArrayList (matchingBeans.values()); 480 Collections.sort(this.handlerMappings, new OrderComparator()); 482 } 483 } 484 else { 485 try { 486 Object hm = getWebApplicationContext().getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class); 487 this.handlerMappings = Collections.singletonList(hm); 488 } 489 catch (NoSuchBeanDefinitionException ex) { 490 } 492 } 493 494 if (this.handlerMappings == null) { 497 this.handlerMappings = getDefaultStrategies(HandlerMapping.class); 498 if (logger.isDebugEnabled()) { 499 logger.debug("No HandlerMappings found in servlet '" + getServletName() + "': using default"); 500 } 501 } 502 } 503 504 509 private void initHandlerAdapters() { 510 if (this.detectAllHandlerAdapters) { 511 Map matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors( 514 getWebApplicationContext(), HandlerAdapter.class, true, false); 515 if (!matchingBeans.isEmpty()) { 516 this.handlerAdapters = new ArrayList (matchingBeans.values()); 517 Collections.sort(this.handlerAdapters, new OrderComparator()); 519 } 520 } 521 else { 522 try { 523 Object ha = getWebApplicationContext().getBean(HANDLER_ADAPTER_BEAN_NAME, HandlerAdapter.class); 524 this.handlerAdapters = Collections.singletonList(ha); 525 } 526 catch (NoSuchBeanDefinitionException ex) { 527 } 529 } 530 531 if (this.handlerAdapters == null) { 534 this.handlerAdapters = getDefaultStrategies(HandlerAdapter.class); 535 if (logger.isDebugEnabled()) { 536 logger.debug("No HandlerAdapters found in servlet '" + getServletName() + "': using default"); 537 } 538 } 539 } 540 541 546 private void initHandlerExceptionResolvers() { 547 if (this.detectAllHandlerExceptionResolvers) { 548 Map matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors( 551 getWebApplicationContext(), HandlerExceptionResolver.class, true, false); 552 this.handlerExceptionResolvers = new ArrayList (matchingBeans.values()); 553 Collections.sort(this.handlerExceptionResolvers, new OrderComparator()); 555 } 556 else { 557 try { 558 Object her = getWebApplicationContext().getBean( 559 HANDLER_EXCEPTION_RESOLVER_BEAN_NAME, HandlerExceptionResolver.class); 560 this.handlerExceptionResolvers = Collections.singletonList(her); 561 } 562 catch (NoSuchBeanDefinitionException ex) { 563 this.handlerExceptionResolvers = getDefaultStrategies(HandlerExceptionResolver.class); 565 } 566 } 567 } 568 569 573 private void initRequestToViewNameTranslator() { 574 try { 575 this.viewNameTranslator = (RequestToViewNameTranslator) getWebApplicationContext().getBean( 576 REQUEST_TO_VIEW_NAME_TRANSLATOR_BEAN_NAME, RequestToViewNameTranslator.class); 577 if (logger.isDebugEnabled()) { 578 logger.debug("Using RequestToViewNameTranslator [" + this.viewNameTranslator + "]"); 579 } 580 } 581 catch (NoSuchBeanDefinitionException ex) { 582 this.viewNameTranslator = 584 (RequestToViewNameTranslator) getDefaultStrategy(RequestToViewNameTranslator.class); 585 if (logger.isDebugEnabled()) { 586 logger.debug("Unable to locate RequestToViewNameTranslator with name '" + 587 REQUEST_TO_VIEW_NAME_TRANSLATOR_BEAN_NAME + 588 "': using default [" + this.viewNameTranslator + "]"); 589 } 590 } 591 } 592 593 598 private void initViewResolvers() { 599 if (this.detectAllViewResolvers) { 600 Map matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors( 603 getWebApplicationContext(), ViewResolver.class, true, false); 604 if (!matchingBeans.isEmpty()) { 605 this.viewResolvers = new ArrayList (matchingBeans.values()); 606 Collections.sort(this.viewResolvers, new OrderComparator()); 608 } 609 } 610 else { 611 try { 612 Object vr = getWebApplicationContext().getBean(VIEW_RESOLVER_BEAN_NAME, ViewResolver.class); 613 this.viewResolvers = Collections.singletonList(vr); 614 } 615 catch (NoSuchBeanDefinitionException ex) { 616 } 618 } 619 620 if (this.viewResolvers == null) { 623 this.viewResolvers = getDefaultStrategies(ViewResolver.class); 624 if (logger.isDebugEnabled()) { 625 logger.debug("No ViewResolvers found in servlet '" + getServletName() + "': using default"); 626 } 627 } 628 } 629 630 636 public ThemeSource getThemeSource() { 637 if (getWebApplicationContext() instanceof ThemeSource) { 638 return (ThemeSource) getWebApplicationContext(); 639 } 640 else { 641 return null; 642 } 643 } 644 645 646 655 protected Object getDefaultStrategy(Class strategyInterface) throws BeansException { 656 List strategies = getDefaultStrategies(strategyInterface); 657 if (strategies.size() != 1) { 658 throw new BeanInitializationException( 659 "DispatcherServlet needs exactly 1 strategy for interface [" + strategyInterface.getName() + "]"); 660 } 661 return strategies.get(0); 662 } 663 664 673 protected List getDefaultStrategies(Class strategyInterface) throws BeansException { 674 String key = strategyInterface.getName(); 675 List strategies = null; 676 String value = defaultStrategies.getProperty(key); 677 if (value != null) { 678 String [] classNames = StringUtils.commaDelimitedListToStringArray(value); 679 strategies = new ArrayList (classNames.length); 680 for (int i = 0; i < classNames.length; i++) { 681 String className = classNames[i]; 682 try { 683 Class clazz = ClassUtils.forName(className, getClass().getClassLoader()); 684 Object strategy = createDefaultStrategy(clazz); 685 strategies.add(strategy); 686 } 687 catch (ClassNotFoundException ex) { 688 throw new BeanInitializationException( 689 "Could not find DispatcherServlet's default strategy class [" + className + 690 "] for interface [" + key + "]", ex); 691 } 692 catch (LinkageError err) { 693 throw new BeanInitializationException( 694 "Error loading DispatcherServlet's default strategy class [" + className + 695 "] for interface [" + key + "]: problem with class file or dependent class", err); 696 } 697 } 698 } 699 else { 700 strategies = Collections.EMPTY_LIST; 701 } 702 return strategies; 703 } 704 705 716 protected Object createDefaultStrategy(Class clazz) throws BeansException { 717 return getWebApplicationContext().getAutowireCapableBeanFactory().createBean( 718 clazz, AutowireCapableBeanFactory.AUTOWIRE_NO, false); 719 } 720 721 722 726 protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception { 727 if (logger.isDebugEnabled()) { 728 logger.debug("DispatcherServlet with name '" + getServletName() + "' received request for [" + 729 request.getRequestURI() + "]"); 730 } 731 732 Map attributesSnapshot = null; 735 if (WebUtils.isIncludeRequest(request)) { 736 logger.debug("Taking snapshot of request attributes before include"); 737 attributesSnapshot = new HashMap (); 738 Enumeration attrNames = request.getAttributeNames(); 739 while (attrNames.hasMoreElements()) { 740 String attrName = (String ) attrNames.nextElement(); 741 if (this.cleanupAfterInclude || attrName.startsWith(DispatcherServlet.class.getName())) { 742 attributesSnapshot.put(attrName, request.getAttribute(attrName)); 743 } 744 } 745 } 746 747 request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext()); 749 request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver); 750 request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver); 751 request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource()); 752 753 try { 754 doDispatch(request, response); 755 } 756 finally { 757 if (attributesSnapshot != null) { 759 restoreAttributesAfterInclude(request, attributesSnapshot); 760 } 761 } 762 } 763 764 775 protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { 776 HttpServletRequest processedRequest = request; 777 HandlerExecutionChain mappedHandler = null; 778 int interceptorIndex = -1; 779 780 LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext(); 782 LocaleContextHolder.setLocaleContext(buildLocaleContext(request), this.threadContextInheritable); 783 784 RequestAttributes previousRequestAttributes = RequestContextHolder.getRequestAttributes(); 786 ServletRequestAttributes requestAttributes = new ServletRequestAttributes(request); 787 RequestContextHolder.setRequestAttributes(requestAttributes, this.threadContextInheritable); 788 789 if (logger.isDebugEnabled()) { 790 logger.debug("Bound request context to thread: " + request); 791 } 792 793 try { 794 ModelAndView mv = null; 795 try { 796 processedRequest = checkMultipart(request); 797 798 mappedHandler = getHandler(processedRequest, false); 800 if (mappedHandler == null || mappedHandler.getHandler() == null) { 801 noHandlerFound(processedRequest, response); 802 return; 803 } 804 805 if (mappedHandler.getInterceptors() != null) { 807 for (int i = 0; i < mappedHandler.getInterceptors().length; i++) { 808 HandlerInterceptor interceptor = mappedHandler.getInterceptors()[i]; 809 if (!interceptor.preHandle(processedRequest, response, mappedHandler.getHandler())) { 810 triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null); 811 return; 812 } 813 interceptorIndex = i; 814 } 815 } 816 817 HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); 819 mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); 820 821 if (mappedHandler.getInterceptors() != null) { 823 for (int i = mappedHandler.getInterceptors().length - 1; i >= 0; i--) { 824 HandlerInterceptor interceptor = mappedHandler.getInterceptors()[i]; 825 interceptor.postHandle(processedRequest, response, mappedHandler.getHandler(), mv); 826 } 827 } 828 } 829 catch (ModelAndViewDefiningException ex) { 830 logger.debug("ModelAndViewDefiningException encountered", ex); 831 mv = ex.getModelAndView(); 832 } 833 catch (Exception ex) { 834 Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null); 835 mv = processHandlerException(processedRequest, response, handler, ex); 836 } 837 838 if (mv != null && !mv.wasCleared()) { 840 render(mv, processedRequest, response); 841 } 842 else { 843 if (logger.isDebugEnabled()) { 844 logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + 845 getServletName() + "': assuming HandlerAdapter completed request handling"); 846 } 847 } 848 849 triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null); 851 } 852 853 catch (Exception ex) { 854 triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex); 856 throw ex; 857 } 858 catch (Error err) { 859 ServletException ex = new NestedServletException("Handler processing failed", err); 860 triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex); 862 throw ex; 863 } 864 865 finally { 866 if (processedRequest != request) { 868 cleanupMultipart(processedRequest); 869 } 870 871 RequestContextHolder.setRequestAttributes(previousRequestAttributes, this.threadContextInheritable); 873 LocaleContextHolder.setLocaleContext(previousLocaleContext, this.threadContextInheritable); 874 875 requestAttributes.requestCompleted(); 877 if (logger.isDebugEnabled()) { 878 logger.debug("Cleared thread-bound request context: " + request); 879 } 880 } 881 } 882 883 887 protected long getLastModified(HttpServletRequest request) { 888 try { 889 HandlerExecutionChain mappedHandler = getHandler(request, true); 890 if (mappedHandler == null || mappedHandler.getHandler() == null) { 891 logger.debug("No handler found in getLastModified"); 893 return -1; 894 } 895 896 HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); 897 long lastModified = ha.getLastModified(request, mappedHandler.getHandler()); 898 if (logger.isDebugEnabled()) { 899 logger.debug("Last-Modified value for [" + request.getRequestURI() + "] is [" + lastModified + "]"); 900 } 901 return lastModified; 902 } 903 catch (Exception ex) { 904 logger.debug("Exception thrown in getLastModified", ex); 906 return -1; 907 } 908 } 909 910 911 919 protected LocaleContext buildLocaleContext(final HttpServletRequest request) { 920 return new LocaleContext() { 921 public Locale getLocale() { 922 return localeResolver.resolveLocale(request); 923 } 924 }; 925 } 926 927 934 protected HttpServletRequest checkMultipart(HttpServletRequest request) throws MultipartException { 935 if (this.multipartResolver != null && this.multipartResolver.isMultipart(request)) { 936 if (request instanceof MultipartHttpServletRequest) { 937 logger.debug("Request is already a MultipartHttpServletRequest - if not in a forward, " + 938 "this typically results from an additional MultipartFilter in web.xml"); 939 } 940 else { 941 return this.multipartResolver.resolveMultipart(request); 942 } 943 } 944 return request; 946 } 947 948 953 protected void cleanupMultipart(HttpServletRequest request) { 954 if (request instanceof MultipartHttpServletRequest) { 955 this.multipartResolver.cleanupMultipart((MultipartHttpServletRequest) request); 956 } 957 } 958 959 966 protected HandlerExecutionChain getHandler(HttpServletRequest request, boolean cache) throws Exception { 967 HandlerExecutionChain handler = 968 (HandlerExecutionChain) request.getAttribute(HANDLER_EXECUTION_CHAIN_ATTRIBUTE); 969 if (handler != null) { 970 if (!cache) { 971 request.removeAttribute(HANDLER_EXECUTION_CHAIN_ATTRIBUTE); 972 } 973 return handler; 974 } 975 976 Iterator it = this.handlerMappings.iterator(); 977 while (it.hasNext()) { 978 HandlerMapping hm = (HandlerMapping) it.next(); 979 if (logger.isDebugEnabled()) { 980 logger.debug("Testing handler map [" + hm + "] in DispatcherServlet with name '" + 981 getServletName() + "'"); 982 } 983 handler = hm.getHandler(request); 984 if (handler != null) { 985 if (cache) { 986 request.setAttribute(HANDLER_EXECUTION_CHAIN_ATTRIBUTE, handler); 987 } 988 return handler; 989 } 990 } 991 return null; 992 } 993 994 1000 protected void noHandlerFound(HttpServletRequest request, HttpServletResponse response) throws IOException { 1001 if (pageNotFoundLogger.isWarnEnabled()) { 1002 String requestUri = new UrlPathHelper().getRequestUri(request); 1003 pageNotFoundLogger.warn("No mapping for [" + requestUri + 1004 "] in DispatcherServlet with name '" + getServletName() + "'"); 1005 } 1006 response.sendError(HttpServletResponse.SC_NOT_FOUND); 1007 } 1008 1009 1015 protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException { 1016 Iterator it = this.handlerAdapters.iterator(); 1017 while (it.hasNext()) { 1018 HandlerAdapter ha = (HandlerAdapter) it.next(); 1019 if (logger.isDebugEnabled()) { 1020 logger.debug("Testing handler adapter [" + ha + "]"); 1021 } 1022 if (ha.supports(handler)) { 1023 return ha; 1024 } 1025 } 1026 throw new ServletException ("No adapter for handler [" + handler + 1027 "]: Does your handler implement a supported interface like Controller?"); 1028 } 1029 1030 1040 protected ModelAndView processHandlerException( 1041 HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) 1042 throws Exception { 1043 1044 ModelAndView exMv = null; 1045 for (Iterator it = this.handlerExceptionResolvers.iterator(); exMv == null && it.hasNext();) { 1046 HandlerExceptionResolver resolver = (HandlerExceptionResolver) it.next(); 1047 exMv = resolver.resolveException(request, response, handler, ex); 1048 } 1049 if (exMv != null) { 1050 if (logger.isDebugEnabled()) { 1051 logger.debug("Handler execution resulted in exception - forwarding to resolved error view: " + exMv, ex); 1052 } 1053 return exMv; 1054 } 1055 else { 1056 throw ex; 1057 } 1058 } 1059 1060 1068 protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) 1069 throws Exception { 1070 1071 Locale locale = this.localeResolver.resolveLocale(request); 1073 response.setLocale(locale); 1074 1075 View view = null; 1076 1077 if (!mv.hasView()) { 1079 mv.setViewName(getDefaultViewName(request)); 1080 } 1081 1082 if (mv.isReference()) { 1083 view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request); 1085 if (view == null) { 1086 throw new ServletException ("Could not resolve view with name '" + mv.getViewName() + 1087 "' in servlet with name '" + getServletName() + "'"); 1088 } 1089 } 1090 else { 1091 view = mv.getView(); 1093 if (view == null) { 1094 throw new ServletException ("ModelAndView [" + mv + "] neither contains a view name nor a " + 1095 "View object in servlet with name '" + getServletName() + "'"); 1096 } 1097 } 1098 1099 if (logger.isDebugEnabled()) { 1101 logger.debug("Rendering view [" + view + "] in DispatcherServlet with name '" + getServletName() + "'"); 1102 } 1103 view.render(mv.getModelInternal(), request, response); 1104 } 1105 1106 1112 protected String getDefaultViewName(HttpServletRequest request) throws Exception { 1113 String viewName = this.viewNameTranslator.getViewName(request); 1114 if (viewName == null) { 1115 throw new ServletException ("Could not translate request [" + request + 1116 "] into view name using [" + this.viewNameTranslator.getClass().getName() + "]"); 1117 } 1118 return viewName; 1119 } 1120 1121 1135 protected View resolveViewName(String viewName, Map model, Locale locale, HttpServletRequest request) 1136 throws Exception { 1137 1138 for (Iterator it = this.viewResolvers.iterator(); it.hasNext();) { 1139 ViewResolver viewResolver = (ViewResolver) it.next(); 1140 View view = viewResolver.resolveViewName(viewName, locale); 1141 if (view != null) { 1142 return view; 1143 } 1144 } 1145 return null; 1146 } 1147 1148 1157 private void triggerAfterCompletion( 1158 HandlerExecutionChain mappedHandler, int interceptorIndex, 1159 HttpServletRequest request, HttpServletResponse response, Exception ex) 1160 throws Exception { 1161 1162 if (mappedHandler != null) { 1164 if (mappedHandler.getInterceptors() != null) { 1165 for (int i = interceptorIndex; i >= 0; i--) { 1166 HandlerInterceptor interceptor = mappedHandler.getInterceptors()[i]; 1167 try { 1168 interceptor.afterCompletion(request, response, mappedHandler.getHandler(), ex); 1169 } 1170 catch (Throwable ex2) { 1171 logger.error("HandlerInterceptor.afterCompletion threw exception", ex2); 1172 } 1173 } 1174 } 1175 } 1176 } 1177 1178 1184 private void restoreAttributesAfterInclude(HttpServletRequest request, Map attributesSnapshot) { 1185 logger.debug("Restoring snapshot of request attributes after include"); 1186 1187 Set attrsToCheck = new HashSet (); 1190 Enumeration attrNames = request.getAttributeNames(); 1191 while (attrNames.hasMoreElements()) { 1192 String attrName = (String ) attrNames.nextElement(); 1193 if (this.cleanupAfterInclude || attrName.startsWith(DispatcherServlet.class.getName())) { 1194 attrsToCheck.add(attrName); 1195 } 1196 } 1197 1198 for (Iterator it = attrsToCheck.iterator(); it.hasNext();) { 1201 String attrName = (String ) it.next(); 1202 Object attrValue = attributesSnapshot.get(attrName); 1203 if (attrValue != null) { 1204 if (logger.isDebugEnabled()) { 1205 logger.debug("Restoring original value of attribute [" + attrName + "] after include"); 1206 } 1207 request.setAttribute(attrName, attrValue); 1208 } 1209 else { 1210 if (logger.isDebugEnabled()) { 1211 logger.debug("Removing attribute [" + attrName + "] after include"); 1212 } 1213 request.removeAttribute(attrName); 1214 } 1215 } 1216 } 1217 1218} 1219 | Popular Tags |