Source Code Cross Referenced for DispatcherServlet.java in  » J2EE » spring-framework-2.0.6 » org » springframework » web » servlet » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » J2EE » spring framework 2.0.6 » org.springframework.web.servlet 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright 2002-2007 the original author or authors.
0003:         *
0004:         * Licensed under the Apache License, Version 2.0 (the "License");
0005:         * you may not use this file except in compliance with the License.
0006:         * You may obtain a copy of the License at
0007:         *
0008:         *      http://www.apache.org/licenses/LICENSE-2.0
0009:         *
0010:         * Unless required by applicable law or agreed to in writing, software
0011:         * distributed under the License is distributed on an "AS IS" BASIS,
0012:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013:         * See the License for the specific language governing permissions and
0014:         * limitations under the License.
0015:         */
0016:
0017:        package org.springframework.web.servlet;
0018:
0019:        import java.io.IOException;
0020:        import java.util.ArrayList;
0021:        import java.util.Collections;
0022:        import java.util.Enumeration;
0023:        import java.util.HashMap;
0024:        import java.util.HashSet;
0025:        import java.util.Iterator;
0026:        import java.util.List;
0027:        import java.util.Locale;
0028:        import java.util.Map;
0029:        import java.util.Properties;
0030:        import java.util.Set;
0031:
0032:        import javax.servlet.ServletException;
0033:        import javax.servlet.http.HttpServletRequest;
0034:        import javax.servlet.http.HttpServletResponse;
0035:
0036:        import org.apache.commons.logging.Log;
0037:        import org.apache.commons.logging.LogFactory;
0038:
0039:        import org.springframework.beans.BeansException;
0040:        import org.springframework.beans.factory.BeanFactoryUtils;
0041:        import org.springframework.beans.factory.BeanInitializationException;
0042:        import org.springframework.beans.factory.NoSuchBeanDefinitionException;
0043:        import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
0044:        import org.springframework.context.ApplicationContext;
0045:        import org.springframework.context.i18n.LocaleContext;
0046:        import org.springframework.context.i18n.LocaleContextHolder;
0047:        import org.springframework.core.OrderComparator;
0048:        import org.springframework.core.io.ClassPathResource;
0049:        import org.springframework.core.io.support.PropertiesLoaderUtils;
0050:        import org.springframework.ui.context.ThemeSource;
0051:        import org.springframework.util.ClassUtils;
0052:        import org.springframework.util.StringUtils;
0053:        import org.springframework.web.context.request.RequestAttributes;
0054:        import org.springframework.web.context.request.RequestContextHolder;
0055:        import org.springframework.web.context.request.ServletRequestAttributes;
0056:        import org.springframework.web.multipart.MultipartException;
0057:        import org.springframework.web.multipart.MultipartHttpServletRequest;
0058:        import org.springframework.web.multipart.MultipartResolver;
0059:        import org.springframework.web.util.NestedServletException;
0060:        import org.springframework.web.util.UrlPathHelper;
0061:        import org.springframework.web.util.WebUtils;
0062:
0063:        /**
0064:         * Central dispatcher for HTTP request handlers/controllers,
0065:         * e.g. for web UI controllers or HTTP-based remote service exporters.
0066:         * Dispatches to registered handlers for processing a web request,
0067:         * providing convenient mapping and exception handling facilities.
0068:         *
0069:         * <p>This servlet is very flexible: It can be used with just about any workflow,
0070:         * with the installation of the appropriate adapter classes. It offers the
0071:         * following functionality that distinguishes it from other request-driven
0072:         * web MVC frameworks:
0073:         *
0074:         * <ul>
0075:         * <li>It is based around a JavaBeans configuration mechanism.
0076:         *
0077:         * <li>It can use any {@link HandlerMapping} implementation - pre-built or provided
0078:         * as part of an application - to control the routing of requests to handler objects.
0079:         * Default is {@link org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping}.
0080:         * HandlerMapping objects can be defined as beans in the servlet's application context,
0081:         * implementing the HandlerMapping interface, overriding the default HandlerMapping
0082:         * if present. HandlerMappings can be given any bean name (they are tested by type).
0083:         *
0084:         * <li>It can use any {@link HandlerAdapter}; this allows to use any handler interface.
0085:         * Default adapters are {@link org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter},
0086:         * {@link org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter} and
0087:         * {@link org.springframework.web.servlet.mvc.throwaway.ThrowawayControllerHandlerAdapter},
0088:         * for Spring's {@link org.springframework.web.HttpRequestHandler},
0089:         * {@link org.springframework.web.servlet.mvc.Controller} and
0090:         * {@link org.springframework.web.servlet.mvc.throwaway.ThrowawayController} interfaces,
0091:         * respectively. HandlerAdapter objects can be added as beans in the application context,
0092:         * overriding the default HandlerAdapters. Like HandlerMappings, HandlerAdapters
0093:         * can be given any bean name (they are tested by type).
0094:         *
0095:         * <li>The dispatcher's exception resolution strategy can be specified via a
0096:         * {@link HandlerExceptionResolver}, for example mapping certain exceptions to
0097:         * error pages. Default is none. Additional HandlerExceptionResolvers can be added
0098:         * through the application context. HandlerExceptionResolver can be given any
0099:         * bean name (they are tested by type).
0100:         *
0101:         * <li>Its view resolution strategy can be specified via a {@link ViewResolver}
0102:         * implementation, resolving symbolic view names into View objects. Default is
0103:         * {@link org.springframework.web.servlet.view.InternalResourceViewResolver}.
0104:         * ViewResolver objects can be added as beans in the application context,
0105:         * overriding the default ViewResolver. ViewResolvers can be given any bean name
0106:         * (they are tested by type).
0107:         *
0108:         * <li>If a {@link View} or view name is not supplied by the user, then the configured
0109:         * {@link RequestToViewNameTranslator} will translate the current request into a
0110:         * view name. The corresponding bean name is "viewNameTranslator"; the default is
0111:         * {@link org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator}.
0112:         *
0113:         * <li>The dispatcher's strategy for resolving multipart requests is determined by
0114:         * a {@link org.springframework.web.multipart.MultipartResolver} implementation.
0115:         * Implementations for Jakarta Commons FileUpload and Jason Hunter's COS are
0116:         * included; the typical choise is
0117:         * {@link org.springframework.web.multipart.commons.CommonsMultipartResolver}.
0118:         * The MultipartResolver bean name is "multipartResolver"; default is none.
0119:         *
0120:         * <li>Its locale resolution strategy is determined by a {@link LocaleResolver}.
0121:         * Out-of-the-box implementations work via HTTP accept header, cookie, or session.
0122:         * The LocaleResolver bean name is "localeResolver"; default is
0123:         * {@link org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver}.
0124:         *
0125:         * <li>Its theme resolution strategy is determined by a {@link ThemeResolver}.
0126:         * Implementations for a fixed theme and for cookie and session storage are included.
0127:         * The ThemeResolver bean name is "themeResolver"; default is
0128:         * {@link org.springframework.web.servlet.theme.FixedThemeResolver}.
0129:         * </ul>
0130:         *
0131:         * <p><b>A web application can define any number of DispatcherServlets.</b>
0132:         * Each servlet will operate in its own namespace, loading its own application
0133:         * context with mappings, handlers, etc. Only the root application context
0134:         * as loaded by {@link org.springframework.web.context.ContextLoaderListener},
0135:         * if any, will be shared.
0136:         *
0137:         * @author Rod Johnson
0138:         * @author Juergen Hoeller
0139:         * @author Rob Harrop
0140:         * @see org.springframework.web.HttpRequestHandler
0141:         * @see org.springframework.web.servlet.mvc.Controller
0142:         * @see org.springframework.web.context.ContextLoaderListener
0143:         */
0144:        public class DispatcherServlet extends FrameworkServlet {
0145:
0146:            /**
0147:             * Well-known name for the MultipartResolver object in the bean factory for this namespace.
0148:             */
0149:            public static final String MULTIPART_RESOLVER_BEAN_NAME = "multipartResolver";
0150:
0151:            /**
0152:             * Well-known name for the LocaleResolver object in the bean factory for this namespace.
0153:             */
0154:            public static final String LOCALE_RESOLVER_BEAN_NAME = "localeResolver";
0155:
0156:            /**
0157:             * Well-known name for the ThemeResolver object in the bean factory for this namespace.
0158:             */
0159:            public static final String THEME_RESOLVER_BEAN_NAME = "themeResolver";
0160:
0161:            /**
0162:             * Well-known name for the HandlerMapping object in the bean factory for this namespace.
0163:             * Only used when "detectAllHandlerMappings" is turned off.
0164:             * @see #setDetectAllHandlerMappings
0165:             */
0166:            public static final String HANDLER_MAPPING_BEAN_NAME = "handlerMapping";
0167:
0168:            /**
0169:             * Well-known name for the HandlerAdapter object in the bean factory for this namespace.
0170:             * Only used when "detectAllHandlerAdapters" is turned off.
0171:             * @see #setDetectAllHandlerAdapters
0172:             */
0173:            public static final String HANDLER_ADAPTER_BEAN_NAME = "handlerAdapter";
0174:
0175:            /**
0176:             * Well-known name for the HandlerExceptionResolver object in the bean factory for this
0177:             * namespace. Only used when "detectAllHandlerExceptionResolvers" is turned off.
0178:             * @see #setDetectAllHandlerExceptionResolvers
0179:             */
0180:            public static final String HANDLER_EXCEPTION_RESOLVER_BEAN_NAME = "handlerExceptionResolver";
0181:
0182:            /**
0183:             * Well-known name for the RequestToViewNameTranslator object in the bean factory for
0184:             * this namespace.
0185:             */
0186:            public static final String REQUEST_TO_VIEW_NAME_TRANSLATOR_BEAN_NAME = "viewNameTranslator";
0187:
0188:            /**
0189:             * Well-known name for the ViewResolver object in the bean factory for this namespace.
0190:             * Only used when "detectAllViewResolvers" is turned off.
0191:             * @see #setDetectAllViewResolvers
0192:             */
0193:            public static final String VIEW_RESOLVER_BEAN_NAME = "viewResolver";
0194:
0195:            /**
0196:             * Request attribute to hold the currently chosen HandlerExecutionChain.
0197:             * Only used for internal optimizations.
0198:             */
0199:            public static final String HANDLER_EXECUTION_CHAIN_ATTRIBUTE = DispatcherServlet.class
0200:                    .getName()
0201:                    + ".HANDLER";
0202:
0203:            /**
0204:             * Request attribute to hold the current web application context.
0205:             * Otherwise only the global web app context is obtainable by tags etc.
0206:             * @see org.springframework.web.servlet.support.RequestContextUtils#getWebApplicationContext
0207:             */
0208:            public static final String WEB_APPLICATION_CONTEXT_ATTRIBUTE = DispatcherServlet.class
0209:                    .getName()
0210:                    + ".CONTEXT";
0211:
0212:            /**
0213:             * Request attribute to hold the current LocaleResolver, retrievable by views.
0214:             * @see org.springframework.web.servlet.support.RequestContextUtils#getLocaleResolver
0215:             */
0216:            public static final String LOCALE_RESOLVER_ATTRIBUTE = DispatcherServlet.class
0217:                    .getName()
0218:                    + ".LOCALE_RESOLVER";
0219:
0220:            /**
0221:             * Request attribute to hold the current ThemeResolver, retrievable by views.
0222:             * @see org.springframework.web.servlet.support.RequestContextUtils#getThemeResolver
0223:             */
0224:            public static final String THEME_RESOLVER_ATTRIBUTE = DispatcherServlet.class
0225:                    .getName()
0226:                    + ".THEME_RESOLVER";
0227:
0228:            /**
0229:             * Request attribute to hold the current ThemeSource, retrievable by views.
0230:             * @see org.springframework.web.servlet.support.RequestContextUtils#getThemeSource
0231:             */
0232:            public static final String THEME_SOURCE_ATTRIBUTE = DispatcherServlet.class
0233:                    .getName()
0234:                    + ".THEME_SOURCE";
0235:
0236:            /**
0237:             * Log category to use when no mapped handler is found for a request.
0238:             */
0239:            public static final String PAGE_NOT_FOUND_LOG_CATEGORY = "org.springframework.web.servlet.PageNotFound";
0240:
0241:            /**
0242:             * Name of the class path resource (relative to the DispatcherServlet class)
0243:             * that defines DispatcherServlet's default strategy names.
0244:             */
0245:            private static final String DEFAULT_STRATEGIES_PATH = "DispatcherServlet.properties";
0246:
0247:            /**
0248:             * Additional logger to use when no mapped handler is found for a request.
0249:             */
0250:            protected static final Log pageNotFoundLogger = LogFactory
0251:                    .getLog(PAGE_NOT_FOUND_LOG_CATEGORY);
0252:
0253:            private static final Properties defaultStrategies;
0254:
0255:            static {
0256:                // Load default strategy implementations from properties file.
0257:                // This is currently strictly internal and not meant to be customized
0258:                // by application developers.
0259:                try {
0260:                    ClassPathResource resource = new ClassPathResource(
0261:                            DEFAULT_STRATEGIES_PATH, DispatcherServlet.class);
0262:                    defaultStrategies = PropertiesLoaderUtils
0263:                            .loadProperties(resource);
0264:                } catch (IOException ex) {
0265:                    throw new IllegalStateException(
0266:                            "Could not load 'DispatcherServlet.properties': "
0267:                                    + ex.getMessage());
0268:                }
0269:            }
0270:
0271:            /** Detect all HandlerMappings or just expect "handlerMapping" bean? */
0272:            private boolean detectAllHandlerMappings = true;
0273:
0274:            /** Detect all HandlerAdapters or just expect "handlerAdapter" bean? */
0275:            private boolean detectAllHandlerAdapters = true;
0276:
0277:            /** Detect all HandlerExceptionResolvers or just expect "handlerExceptionResolver" bean? */
0278:            private boolean detectAllHandlerExceptionResolvers = true;
0279:
0280:            /** Detect all ViewResolvers or just expect "viewResolver" bean? */
0281:            private boolean detectAllViewResolvers = true;
0282:
0283:            /** Perform cleanup of request attributes after include request? */
0284:            private boolean cleanupAfterInclude = true;
0285:
0286:            /** Expose LocaleContext and RequestAttributes as inheritable for child threads? */
0287:            private boolean threadContextInheritable = false;
0288:
0289:            /** MultipartResolver used by this servlet */
0290:            private MultipartResolver multipartResolver;
0291:
0292:            /** LocaleResolver used by this servlet */
0293:            private LocaleResolver localeResolver;
0294:
0295:            /** ThemeResolver used by this servlet */
0296:            private ThemeResolver themeResolver;
0297:
0298:            /** List of HandlerMappings used by this servlet */
0299:            private List handlerMappings;
0300:
0301:            /** List of HandlerAdapters used by this servlet */
0302:            private List handlerAdapters;
0303:
0304:            /** List of HandlerExceptionResolvers used by this servlet */
0305:            private List handlerExceptionResolvers;
0306:
0307:            /** RequestToViewNameTranslator used by this servlet */
0308:            private RequestToViewNameTranslator viewNameTranslator;
0309:
0310:            /** List of ViewResolvers used by this servlet */
0311:            private List viewResolvers;
0312:
0313:            /**
0314:             * Set whether to detect all HandlerMapping beans in this servlet's context.
0315:             * Else, just a single bean with name "handlerMapping" will be expected.
0316:             * <p>Default is "true". Turn this off if you want this servlet to use a
0317:             * single HandlerMapping, despite multiple HandlerMapping beans being
0318:             * defined in the context.
0319:             */
0320:            public void setDetectAllHandlerMappings(
0321:                    boolean detectAllHandlerMappings) {
0322:                this .detectAllHandlerMappings = detectAllHandlerMappings;
0323:            }
0324:
0325:            /**
0326:             * Set whether to detect all HandlerAdapter beans in this servlet's context.
0327:             * Else, just a single bean with name "handlerAdapter" will be expected.
0328:             * <p>Default is "true". Turn this off if you want this servlet to use a
0329:             * single HandlerAdapter, despite multiple HandlerAdapter beans being
0330:             * defined in the context.
0331:             */
0332:            public void setDetectAllHandlerAdapters(
0333:                    boolean detectAllHandlerAdapters) {
0334:                this .detectAllHandlerAdapters = detectAllHandlerAdapters;
0335:            }
0336:
0337:            /**
0338:             * Set whether to detect all HandlerExceptionResolver beans in this servlet's context.
0339:             * Else, just a single bean with name "handlerExceptionResolver" will be expected.
0340:             * <p>Default is "true". Turn this off if you want this servlet to use a
0341:             * single HandlerExceptionResolver, despite multiple HandlerExceptionResolver
0342:             * beans being defined in the context.
0343:             */
0344:            public void setDetectAllHandlerExceptionResolvers(
0345:                    boolean detectAllHandlerExceptionResolvers) {
0346:                this .detectAllHandlerExceptionResolvers = detectAllHandlerExceptionResolvers;
0347:            }
0348:
0349:            /**
0350:             * Set whether to detect all ViewResolver beans in this servlet's context.
0351:             * Else, just a single bean with name "viewResolver" will be expected.
0352:             * <p>Default is "true". Turn this off if you want this servlet to use a
0353:             * single ViewResolver, despite multiple ViewResolver beans being
0354:             * defined in the context.
0355:             */
0356:            public void setDetectAllViewResolvers(boolean detectAllViewResolvers) {
0357:                this .detectAllViewResolvers = detectAllViewResolvers;
0358:            }
0359:
0360:            /**
0361:             * Set whether to perform cleanup of request attributes after an include request,
0362:             * that is, whether to reset the original state of all request attributes after
0363:             * the DispatcherServlet has processed within an include request. Else, just the
0364:             * DispatcherServlet's own request attributes will be reset, but not model
0365:             * attributes for JSPs or special attributes set by views (for example, JSTL's).
0366:             * <p>Default is "true", which is strongly recommended. Views should not rely on
0367:             * request attributes having been set by (dynamic) includes. This allows JSP views
0368:             * rendered by an included controller to use any model attributes, even with the
0369:             * same names as in the main JSP, without causing side effects. Only turn this
0370:             * off for special needs, for example to deliberately allow main JSPs to access
0371:             * attributes from JSP views rendered by an included controller.
0372:             */
0373:            public void setCleanupAfterInclude(boolean cleanupAfterInclude) {
0374:                this .cleanupAfterInclude = cleanupAfterInclude;
0375:            }
0376:
0377:            /**
0378:             * Set whether to expose the LocaleContext and RequestAttributes as inheritable
0379:             * for child threads (using an {@link java.lang.InheritableThreadLocal}).
0380:             * <p>Default is "false", to avoid side effects on spawned background threads.
0381:             * Switch this to "true" to enable inheritance for custom child threads which
0382:             * are spawned during request processing and only used for this request
0383:             * (that is, ending after their initial task, without reuse of the thread).
0384:             * <p><b>WARNING:</b> Do not use inheritance for child threads if you are
0385:             * accessing a thread pool which is configured to potentially add new threads
0386:             * on demand (e.g. a JDK {@link java.util.concurrent.ThreadPoolExecutor}),
0387:             * since this will expose the inherited context to such a pooled thread.
0388:             */
0389:            public void setThreadContextInheritable(
0390:                    boolean threadContextInheritable) {
0391:                this .threadContextInheritable = threadContextInheritable;
0392:            }
0393:
0394:            /**
0395:             * This implementation calls {@link #initStrategies}.
0396:             */
0397:            protected void onRefresh(ApplicationContext context)
0398:                    throws BeansException {
0399:                initStrategies(context);
0400:            }
0401:
0402:            /**
0403:             * Initialize the strategy objects that this servlet uses.
0404:             * <p>May be overridden in subclasses in order to initialize
0405:             * further strategy objects.
0406:             */
0407:            protected void initStrategies(ApplicationContext context) {
0408:                initMultipartResolver(context);
0409:                initLocaleResolver(context);
0410:                initThemeResolver(context);
0411:                initHandlerMappings(context);
0412:                initHandlerAdapters(context);
0413:                initHandlerExceptionResolvers(context);
0414:                initRequestToViewNameTranslator(context);
0415:                initViewResolvers(context);
0416:            }
0417:
0418:            /**
0419:             * Initialize the MultipartResolver used by this class.
0420:             * <p>If no bean is defined with the given name in the BeanFactory
0421:             * for this namespace, no multipart handling is provided.
0422:             */
0423:            private void initMultipartResolver(ApplicationContext context) {
0424:                try {
0425:                    this .multipartResolver = (MultipartResolver) context
0426:                            .getBean(MULTIPART_RESOLVER_BEAN_NAME,
0427:                                    MultipartResolver.class);
0428:                    if (logger.isDebugEnabled()) {
0429:                        logger.debug("Using MultipartResolver ["
0430:                                + this .multipartResolver + "]");
0431:                    }
0432:                } catch (NoSuchBeanDefinitionException ex) {
0433:                    // Default is no multipart resolver.
0434:                    this .multipartResolver = null;
0435:                    if (logger.isDebugEnabled()) {
0436:                        logger
0437:                                .debug("Unable to locate MultipartResolver with name '"
0438:                                        + MULTIPART_RESOLVER_BEAN_NAME
0439:                                        + "': no multipart request handling provided");
0440:                    }
0441:                }
0442:            }
0443:
0444:            /**
0445:             * Initialize the LocaleResolver used by this class.
0446:             * <p>If no bean is defined with the given name in the BeanFactory
0447:             * for this namespace, we default to AcceptHeaderLocaleResolver.
0448:             */
0449:            private void initLocaleResolver(ApplicationContext context) {
0450:                try {
0451:                    this .localeResolver = (LocaleResolver) context.getBean(
0452:                            LOCALE_RESOLVER_BEAN_NAME, LocaleResolver.class);
0453:                    if (logger.isDebugEnabled()) {
0454:                        logger.debug("Using LocaleResolver ["
0455:                                + this .localeResolver + "]");
0456:                    }
0457:                } catch (NoSuchBeanDefinitionException ex) {
0458:                    // We need to use the default.
0459:                    this .localeResolver = (LocaleResolver) getDefaultStrategy(
0460:                            context, LocaleResolver.class);
0461:                    if (logger.isDebugEnabled()) {
0462:                        logger
0463:                                .debug("Unable to locate LocaleResolver with name '"
0464:                                        + LOCALE_RESOLVER_BEAN_NAME
0465:                                        + "': using default ["
0466:                                        + this .localeResolver + "]");
0467:                    }
0468:                }
0469:            }
0470:
0471:            /**
0472:             * Initialize the ThemeResolver used by this class.
0473:             * <p>If no bean is defined with the given name in the BeanFactory
0474:             * for this namespace, we default to a FixedThemeResolver.
0475:             */
0476:            private void initThemeResolver(ApplicationContext context) {
0477:                try {
0478:                    this .themeResolver = (ThemeResolver) context.getBean(
0479:                            THEME_RESOLVER_BEAN_NAME, ThemeResolver.class);
0480:                    if (logger.isDebugEnabled()) {
0481:                        logger.debug("Using ThemeResolver ["
0482:                                + this .themeResolver + "]");
0483:                    }
0484:                } catch (NoSuchBeanDefinitionException ex) {
0485:                    // We need to use the default.
0486:                    this .themeResolver = (ThemeResolver) getDefaultStrategy(
0487:                            context, ThemeResolver.class);
0488:                    if (logger.isDebugEnabled()) {
0489:                        logger
0490:                                .debug("Unable to locate ThemeResolver with name '"
0491:                                        + THEME_RESOLVER_BEAN_NAME
0492:                                        + "': using default ["
0493:                                        + this .themeResolver + "]");
0494:                    }
0495:                }
0496:            }
0497:
0498:            /**
0499:             * Initialize the HandlerMappings used by this class.
0500:             * <p>If no HandlerMapping beans are defined in the BeanFactory
0501:             * for this namespace, we default to BeanNameUrlHandlerMapping.
0502:             */
0503:            private void initHandlerMappings(ApplicationContext context) {
0504:                this .handlerMappings = null;
0505:
0506:                if (this .detectAllHandlerMappings) {
0507:                    // Find all HandlerMappings in the ApplicationContext,
0508:                    // including ancestor contexts.
0509:                    Map matchingBeans = BeanFactoryUtils
0510:                            .beansOfTypeIncludingAncestors(context,
0511:                                    HandlerMapping.class, true, false);
0512:                    if (!matchingBeans.isEmpty()) {
0513:                        this .handlerMappings = new ArrayList(matchingBeans
0514:                                .values());
0515:                        // We keep HandlerMappings in sorted order.
0516:                        Collections.sort(this .handlerMappings,
0517:                                new OrderComparator());
0518:                    }
0519:                } else {
0520:                    try {
0521:                        Object hm = context.getBean(HANDLER_MAPPING_BEAN_NAME,
0522:                                HandlerMapping.class);
0523:                        this .handlerMappings = Collections.singletonList(hm);
0524:                    } catch (NoSuchBeanDefinitionException ex) {
0525:                        // Ignore, we'll add a default HandlerMapping later.
0526:                    }
0527:                }
0528:
0529:                // Ensure we have at least one HandlerMapping, by registering
0530:                // a default HandlerMapping if no other mappings are found.
0531:                if (this .handlerMappings == null) {
0532:                    this .handlerMappings = getDefaultStrategies(context,
0533:                            HandlerMapping.class);
0534:                    if (logger.isDebugEnabled()) {
0535:                        logger.debug("No HandlerMappings found in servlet '"
0536:                                + getServletName() + "': using default");
0537:                    }
0538:                }
0539:            }
0540:
0541:            /**
0542:             * Initialize the HandlerAdapters used by this class.
0543:             * <p>If no HandlerAdapter beans are defined in the BeanFactory
0544:             * for this namespace, we default to SimpleControllerHandlerAdapter.
0545:             */
0546:            private void initHandlerAdapters(ApplicationContext context) {
0547:                this .handlerAdapters = null;
0548:
0549:                if (this .detectAllHandlerAdapters) {
0550:                    // Find all HandlerAdapters in the ApplicationContext,
0551:                    // including ancestor contexts.
0552:                    Map matchingBeans = BeanFactoryUtils
0553:                            .beansOfTypeIncludingAncestors(context,
0554:                                    HandlerAdapter.class, true, false);
0555:                    if (!matchingBeans.isEmpty()) {
0556:                        this .handlerAdapters = new ArrayList(matchingBeans
0557:                                .values());
0558:                        // We keep HandlerAdapters in sorted order.
0559:                        Collections.sort(this .handlerAdapters,
0560:                                new OrderComparator());
0561:                    }
0562:                } else {
0563:                    try {
0564:                        Object ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME,
0565:                                HandlerAdapter.class);
0566:                        this .handlerAdapters = Collections.singletonList(ha);
0567:                    } catch (NoSuchBeanDefinitionException ex) {
0568:                        // Ignore, we'll add a default HandlerAdapter later.
0569:                    }
0570:                }
0571:
0572:                // Ensure we have at least some HandlerAdapters, by registering
0573:                // default HandlerAdapters if no other adapters are found.
0574:                if (this .handlerAdapters == null) {
0575:                    this .handlerAdapters = getDefaultStrategies(context,
0576:                            HandlerAdapter.class);
0577:                    if (logger.isDebugEnabled()) {
0578:                        logger.debug("No HandlerAdapters found in servlet '"
0579:                                + getServletName() + "': using default");
0580:                    }
0581:                }
0582:            }
0583:
0584:            /**
0585:             * Initialize the HandlerExceptionResolver used by this class.
0586:             * <p>If no bean is defined with the given name in the BeanFactory
0587:             * for this namespace, we default to no exception resolver.
0588:             */
0589:            private void initHandlerExceptionResolvers(
0590:                    ApplicationContext context) {
0591:                this .handlerExceptionResolvers = null;
0592:
0593:                if (this .detectAllHandlerExceptionResolvers) {
0594:                    // Find all HandlerExceptionResolvers in the ApplicationContext,
0595:                    // including ancestor contexts.
0596:                    Map matchingBeans = BeanFactoryUtils
0597:                            .beansOfTypeIncludingAncestors(context,
0598:                                    HandlerExceptionResolver.class, true, false);
0599:                    if (!matchingBeans.isEmpty()) {
0600:                        this .handlerExceptionResolvers = new ArrayList(
0601:                                matchingBeans.values());
0602:                        // We keep HandlerExceptionResolvers in sorted order.
0603:                        Collections.sort(this .handlerExceptionResolvers,
0604:                                new OrderComparator());
0605:                    }
0606:                } else {
0607:                    try {
0608:                        Object her = context.getBean(
0609:                                HANDLER_EXCEPTION_RESOLVER_BEAN_NAME,
0610:                                HandlerExceptionResolver.class);
0611:                        this .handlerExceptionResolvers = Collections
0612:                                .singletonList(her);
0613:                    } catch (NoSuchBeanDefinitionException ex) {
0614:                        // Ignore, no HandlerExceptionResolver is fine too.
0615:                    }
0616:                }
0617:
0618:                // Just for consistency, check for default HandlerExceptionResolvers...
0619:                // There aren't any in usual scenarios.
0620:                if (this .handlerExceptionResolvers == null) {
0621:                    this .handlerExceptionResolvers = getDefaultStrategies(
0622:                            context, HandlerExceptionResolver.class);
0623:                    if (logger.isDebugEnabled()) {
0624:                        logger
0625:                                .debug("No HandlerExceptionResolvers found in servlet '"
0626:                                        + getServletName() + "': using default");
0627:                    }
0628:                }
0629:            }
0630:
0631:            /**
0632:             * Initialize the RequestToViewNameTranslator used by this servlet instance. If no
0633:             * implementation is configured then we default to DefaultRequestToViewNameTranslator.
0634:             */
0635:            private void initRequestToViewNameTranslator(
0636:                    ApplicationContext context) {
0637:                try {
0638:                    this .viewNameTranslator = (RequestToViewNameTranslator) context
0639:                            .getBean(REQUEST_TO_VIEW_NAME_TRANSLATOR_BEAN_NAME,
0640:                                    RequestToViewNameTranslator.class);
0641:                    if (logger.isDebugEnabled()) {
0642:                        logger.debug("Using RequestToViewNameTranslator ["
0643:                                + this .viewNameTranslator + "]");
0644:                    }
0645:                } catch (NoSuchBeanDefinitionException ex) {
0646:                    // We need to use the default.
0647:                    this .viewNameTranslator = (RequestToViewNameTranslator) getDefaultStrategy(
0648:                            context, RequestToViewNameTranslator.class);
0649:                    if (logger.isDebugEnabled()) {
0650:                        logger
0651:                                .debug("Unable to locate RequestToViewNameTranslator with name '"
0652:                                        + REQUEST_TO_VIEW_NAME_TRANSLATOR_BEAN_NAME
0653:                                        + "': using default ["
0654:                                        + this .viewNameTranslator + "]");
0655:                    }
0656:                }
0657:            }
0658:
0659:            /**
0660:             * Initialize the ViewResolvers used by this class.
0661:             * <p>If no ViewResolver beans are defined in the BeanFactory
0662:             * for this namespace, we default to InternalResourceViewResolver.
0663:             */
0664:            private void initViewResolvers(ApplicationContext context) {
0665:                this .viewResolvers = null;
0666:
0667:                if (this .detectAllViewResolvers) {
0668:                    // Find all ViewResolvers in the ApplicationContext,
0669:                    // including ancestor contexts.
0670:                    Map matchingBeans = BeanFactoryUtils
0671:                            .beansOfTypeIncludingAncestors(context,
0672:                                    ViewResolver.class, true, false);
0673:                    if (!matchingBeans.isEmpty()) {
0674:                        this .viewResolvers = new ArrayList(matchingBeans
0675:                                .values());
0676:                        // We keep ViewResolvers in sorted order.
0677:                        Collections.sort(this .viewResolvers,
0678:                                new OrderComparator());
0679:                    }
0680:                } else {
0681:                    try {
0682:                        Object vr = context.getBean(VIEW_RESOLVER_BEAN_NAME,
0683:                                ViewResolver.class);
0684:                        this .viewResolvers = Collections.singletonList(vr);
0685:                    } catch (NoSuchBeanDefinitionException ex) {
0686:                        // Ignore, we'll add a default ViewResolver later.
0687:                    }
0688:                }
0689:
0690:                // Ensure we have at least one ViewResolver, by registering
0691:                // a default ViewResolver if no other resolvers are found.
0692:                if (this .viewResolvers == null) {
0693:                    this .viewResolvers = getDefaultStrategies(context,
0694:                            ViewResolver.class);
0695:                    if (logger.isDebugEnabled()) {
0696:                        logger.debug("No ViewResolvers found in servlet '"
0697:                                + getServletName() + "': using default");
0698:                    }
0699:                }
0700:            }
0701:
0702:            /**
0703:             * Return this servlet's ThemeSource, if any; else return <code>null</code>.
0704:             * <p>Default is to return the WebApplicationContext as ThemeSource,
0705:             * provided that it implements the ThemeSource interface.
0706:             * @return the ThemeSource, if any
0707:             * @see #getWebApplicationContext()
0708:             */
0709:            public ThemeSource getThemeSource() {
0710:                if (getWebApplicationContext() instanceof  ThemeSource) {
0711:                    return (ThemeSource) getWebApplicationContext();
0712:                } else {
0713:                    return null;
0714:                }
0715:            }
0716:
0717:            /**
0718:             * Return the default strategy object for the given strategy interface.
0719:             * <p>The default implementation delegates to {@link #getDefaultStrategies},
0720:             * expecting a single object in the list.
0721:             * @param context the current WebApplicationContext
0722:             * @param strategyInterface the strategy interface
0723:             * @return the corresponding strategy object
0724:             * @throws BeansException if initialization failed
0725:             * @see #getDefaultStrategies
0726:             */
0727:            protected Object getDefaultStrategy(ApplicationContext context,
0728:                    Class strategyInterface) throws BeansException {
0729:                List strategies = getDefaultStrategies(context,
0730:                        strategyInterface);
0731:                if (strategies.size() != 1) {
0732:                    throw new BeanInitializationException(
0733:                            "DispatcherServlet needs exactly 1 strategy for interface ["
0734:                                    + strategyInterface.getName() + "]");
0735:                }
0736:                return strategies.get(0);
0737:            }
0738:
0739:            /**
0740:             * Create a List of default strategy objects for the given strategy interface.
0741:             * <p>The default implementation uses the "DispatcherServlet.properties" file
0742:             * (in the same package as the DispatcherServlet class) to determine the class names.
0743:             * It instantiates the strategy objects through the context's BeanFactory.
0744:             * @param context the current WebApplicationContext
0745:             * @param strategyInterface the strategy interface
0746:             * @return the List of corresponding strategy objects
0747:             * @throws BeansException if initialization failed
0748:             */
0749:            protected List getDefaultStrategies(ApplicationContext context,
0750:                    Class strategyInterface) throws BeansException {
0751:                String key = strategyInterface.getName();
0752:                List strategies = null;
0753:                String value = defaultStrategies.getProperty(key);
0754:                if (value != null) {
0755:                    String[] classNames = StringUtils
0756:                            .commaDelimitedListToStringArray(value);
0757:                    strategies = new ArrayList(classNames.length);
0758:                    for (int i = 0; i < classNames.length; i++) {
0759:                        String className = classNames[i];
0760:                        try {
0761:                            Class clazz = ClassUtils.forName(className,
0762:                                    getClass().getClassLoader());
0763:                            Object strategy = createDefaultStrategy(context,
0764:                                    clazz);
0765:                            strategies.add(strategy);
0766:                        } catch (ClassNotFoundException ex) {
0767:                            throw new BeanInitializationException(
0768:                                    "Could not find DispatcherServlet's default strategy class ["
0769:                                            + className + "] for interface ["
0770:                                            + key + "]", ex);
0771:                        } catch (LinkageError err) {
0772:                            throw new BeanInitializationException(
0773:                                    "Error loading DispatcherServlet's default strategy class ["
0774:                                            + className
0775:                                            + "] for interface ["
0776:                                            + key
0777:                                            + "]: problem with class file or dependent class",
0778:                                    err);
0779:                        }
0780:                    }
0781:                } else {
0782:                    strategies = Collections.EMPTY_LIST;
0783:                }
0784:                return strategies;
0785:            }
0786:
0787:            /**
0788:             * Create a default strategy.
0789:             * <p>The default implementation uses
0790:             * {@link org.springframework.beans.factory.config.AutowireCapableBeanFactory#createBean}.
0791:             * @param context the current WebApplicationContext
0792:             * @param clazz the strategy implementation class to instantiate
0793:             * @throws BeansException if initialization failed
0794:             * @return the fully configured strategy instance
0795:             * @see org.springframework.context.ApplicationContext#getAutowireCapableBeanFactory()
0796:             * @see org.springframework.beans.factory.config.AutowireCapableBeanFactory#createBean
0797:             */
0798:            protected Object createDefaultStrategy(ApplicationContext context,
0799:                    Class clazz) throws BeansException {
0800:                return context.getAutowireCapableBeanFactory().createBean(
0801:                        clazz, AutowireCapableBeanFactory.AUTOWIRE_NO, false);
0802:            }
0803:
0804:            /**
0805:             * Obtain this servlet's MultipartResolver, if any.
0806:             * @return the MultipartResolver used by this servlet, or <code>null</code>
0807:             * if none (indicating that no multipart support is available)
0808:             */
0809:            public MultipartResolver getMultipartResolver() {
0810:                return this .multipartResolver;
0811:            }
0812:
0813:            /**
0814:             * Exposes the DispatcherServlet-specific request attributes and
0815:             * delegates to {@link #doDispatch} for the actual dispatching.
0816:             */
0817:            protected void doService(HttpServletRequest request,
0818:                    HttpServletResponse response) throws Exception {
0819:                if (logger.isDebugEnabled()) {
0820:                    logger.debug("DispatcherServlet with name '"
0821:                            + getServletName() + "' received request for ["
0822:                            + request.getRequestURI() + "]");
0823:                }
0824:
0825:                // Keep a snapshot of the request attributes in case of an include,
0826:                // to be able to restore the original attributes after the include.
0827:                Map attributesSnapshot = null;
0828:                if (WebUtils.isIncludeRequest(request)) {
0829:                    logger
0830:                            .debug("Taking snapshot of request attributes before include");
0831:                    attributesSnapshot = new HashMap();
0832:                    Enumeration attrNames = request.getAttributeNames();
0833:                    while (attrNames.hasMoreElements()) {
0834:                        String attrName = (String) attrNames.nextElement();
0835:                        if (this .cleanupAfterInclude
0836:                                || attrName.startsWith(DispatcherServlet.class
0837:                                        .getName())) {
0838:                            attributesSnapshot.put(attrName, request
0839:                                    .getAttribute(attrName));
0840:                        }
0841:                    }
0842:                }
0843:
0844:                // Make framework objects available to handlers and view objects.
0845:                request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE,
0846:                        getWebApplicationContext());
0847:                request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE,
0848:                        this .localeResolver);
0849:                request.setAttribute(THEME_RESOLVER_ATTRIBUTE,
0850:                        this .themeResolver);
0851:                request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());
0852:
0853:                try {
0854:                    doDispatch(request, response);
0855:                } finally {
0856:                    // Restore the original attribute snapshot, in case of an include.
0857:                    if (attributesSnapshot != null) {
0858:                        restoreAttributesAfterInclude(request,
0859:                                attributesSnapshot);
0860:                    }
0861:                }
0862:            }
0863:
0864:            /**
0865:             * Process the actual dispatching to the handler.
0866:             * <p>The handler will be obtained by applying the servlet's HandlerMappings in order.
0867:             * The HandlerAdapter will be obtained by querying the servlet's installed
0868:             * HandlerAdapters to find the first that supports the handler class.
0869:             * <p>All HTTP methods are handled by this method. It's up to HandlerAdapters or
0870:             * handlers themselves to decide which methods are acceptable.
0871:             * @param request current HTTP request
0872:             * @param response current HTTP response
0873:             * @throws Exception in case of any kind of processing failure
0874:             */
0875:            protected void doDispatch(HttpServletRequest request,
0876:                    HttpServletResponse response) throws Exception {
0877:                HttpServletRequest processedRequest = request;
0878:                HandlerExecutionChain mappedHandler = null;
0879:                int interceptorIndex = -1;
0880:
0881:                // Expose current LocaleResolver and request as LocaleContext.
0882:                LocaleContext previousLocaleContext = LocaleContextHolder
0883:                        .getLocaleContext();
0884:                LocaleContextHolder.setLocaleContext(
0885:                        buildLocaleContext(request),
0886:                        this .threadContextInheritable);
0887:
0888:                // Expose current RequestAttributes to current thread.
0889:                RequestAttributes previousRequestAttributes = RequestContextHolder
0890:                        .getRequestAttributes();
0891:                ServletRequestAttributes requestAttributes = new ServletRequestAttributes(
0892:                        request);
0893:                RequestContextHolder.setRequestAttributes(requestAttributes,
0894:                        this .threadContextInheritable);
0895:
0896:                if (logger.isDebugEnabled()) {
0897:                    logger.debug("Bound request context to thread: " + request);
0898:                }
0899:
0900:                try {
0901:                    ModelAndView mv = null;
0902:                    try {
0903:                        processedRequest = checkMultipart(request);
0904:
0905:                        // Determine handler for the current request.
0906:                        mappedHandler = getHandler(processedRequest, false);
0907:                        if (mappedHandler == null
0908:                                || mappedHandler.getHandler() == null) {
0909:                            noHandlerFound(processedRequest, response);
0910:                            return;
0911:                        }
0912:
0913:                        // Apply preHandle methods of registered interceptors.
0914:                        if (mappedHandler.getInterceptors() != null) {
0915:                            for (int i = 0; i < mappedHandler.getInterceptors().length; i++) {
0916:                                HandlerInterceptor interceptor = mappedHandler
0917:                                        .getInterceptors()[i];
0918:                                if (!interceptor.preHandle(processedRequest,
0919:                                        response, mappedHandler.getHandler())) {
0920:                                    triggerAfterCompletion(mappedHandler,
0921:                                            interceptorIndex, processedRequest,
0922:                                            response, null);
0923:                                    return;
0924:                                }
0925:                                interceptorIndex = i;
0926:                            }
0927:                        }
0928:
0929:                        // Actually invoke the handler.
0930:                        HandlerAdapter ha = getHandlerAdapter(mappedHandler
0931:                                .getHandler());
0932:                        mv = ha.handle(processedRequest, response,
0933:                                mappedHandler.getHandler());
0934:
0935:                        // Apply postHandle methods of registered interceptors.
0936:                        if (mappedHandler.getInterceptors() != null) {
0937:                            for (int i = mappedHandler.getInterceptors().length - 1; i >= 0; i--) {
0938:                                HandlerInterceptor interceptor = mappedHandler
0939:                                        .getInterceptors()[i];
0940:                                interceptor.postHandle(processedRequest,
0941:                                        response, mappedHandler.getHandler(),
0942:                                        mv);
0943:                            }
0944:                        }
0945:                    } catch (ModelAndViewDefiningException ex) {
0946:                        logger
0947:                                .debug(
0948:                                        "ModelAndViewDefiningException encountered",
0949:                                        ex);
0950:                        mv = ex.getModelAndView();
0951:                    } catch (Exception ex) {
0952:                        Object handler = (mappedHandler != null ? mappedHandler
0953:                                .getHandler() : null);
0954:                        mv = processHandlerException(processedRequest,
0955:                                response, handler, ex);
0956:                    }
0957:
0958:                    // Did the handler return a view to render?
0959:                    if (mv != null && !mv.wasCleared()) {
0960:                        render(mv, processedRequest, response);
0961:                    } else {
0962:                        if (logger.isDebugEnabled()) {
0963:                            logger
0964:                                    .debug("Null ModelAndView returned to DispatcherServlet with name '"
0965:                                            + getServletName()
0966:                                            + "': assuming HandlerAdapter completed request handling");
0967:                        }
0968:                    }
0969:
0970:                    // Trigger after-completion for successful outcome.
0971:                    triggerAfterCompletion(mappedHandler, interceptorIndex,
0972:                            processedRequest, response, null);
0973:                }
0974:
0975:                catch (Exception ex) {
0976:                    // Trigger after-completion for thrown exception.
0977:                    triggerAfterCompletion(mappedHandler, interceptorIndex,
0978:                            processedRequest, response, ex);
0979:                    throw ex;
0980:                } catch (Error err) {
0981:                    ServletException ex = new NestedServletException(
0982:                            "Handler processing failed", err);
0983:                    // Trigger after-completion for thrown exception.
0984:                    triggerAfterCompletion(mappedHandler, interceptorIndex,
0985:                            processedRequest, response, ex);
0986:                    throw ex;
0987:                }
0988:
0989:                finally {
0990:                    // Clean up any resources used by a multipart request.
0991:                    if (processedRequest != request) {
0992:                        cleanupMultipart(processedRequest);
0993:                    }
0994:
0995:                    // Reset thread-bound context.
0996:                    RequestContextHolder.setRequestAttributes(
0997:                            previousRequestAttributes,
0998:                            this .threadContextInheritable);
0999:                    LocaleContextHolder.setLocaleContext(previousLocaleContext,
1000:                            this .threadContextInheritable);
1001:
1002:                    // Clear request attributes.
1003:                    requestAttributes.requestCompleted();
1004:                    if (logger.isDebugEnabled()) {
1005:                        logger.debug("Cleared thread-bound request context: "
1006:                                + request);
1007:                    }
1008:                }
1009:            }
1010:
1011:            /**
1012:             * Override HttpServlet's <code>getLastModified</code> method to evaluate
1013:             * the Last-Modified value of the mapped handler.
1014:             */
1015:            protected long getLastModified(HttpServletRequest request) {
1016:                try {
1017:                    HandlerExecutionChain mappedHandler = getHandler(request,
1018:                            true);
1019:                    if (mappedHandler == null
1020:                            || mappedHandler.getHandler() == null) {
1021:                        // Ignore -> will reappear on doService.
1022:                        logger.debug("No handler found in getLastModified");
1023:                        return -1;
1024:                    }
1025:
1026:                    HandlerAdapter ha = getHandlerAdapter(mappedHandler
1027:                            .getHandler());
1028:                    long lastModified = ha.getLastModified(request,
1029:                            mappedHandler.getHandler());
1030:                    if (logger.isDebugEnabled()) {
1031:                        logger.debug("Last-Modified value for ["
1032:                                + request.getRequestURI() + "] is ["
1033:                                + lastModified + "]");
1034:                    }
1035:                    return lastModified;
1036:                } catch (Exception ex) {
1037:                    // Ignore -> will reappear on doService.
1038:                    logger.debug("Exception thrown in getLastModified", ex);
1039:                    return -1;
1040:                }
1041:            }
1042:
1043:            /**
1044:             * Build a LocaleContext for the given request, exposing the request's
1045:             * primary locale as current locale.
1046:             * <p>The default implementation uses the dispatcher's LocaleResolver
1047:             * to obtain the current locale, which might change during a request.
1048:             * @param request current HTTP request
1049:             * @return the corresponding LocaleContext
1050:             */
1051:            protected LocaleContext buildLocaleContext(
1052:                    final HttpServletRequest request) {
1053:                return new LocaleContext() {
1054:                    public Locale getLocale() {
1055:                        return localeResolver.resolveLocale(request);
1056:                    }
1057:                };
1058:            }
1059:
1060:            /**
1061:             * Convert the request into a multipart request, and make multipart resolver available.
1062:             * If no multipart resolver is set, simply use the existing request.
1063:             * @param request current HTTP request
1064:             * @return the processed request (multipart wrapper if necessary)
1065:             * @see MultipartResolver#resolveMultipart
1066:             */
1067:            protected HttpServletRequest checkMultipart(
1068:                    HttpServletRequest request) throws MultipartException {
1069:                if (this .multipartResolver != null
1070:                        && this .multipartResolver.isMultipart(request)) {
1071:                    if (request instanceof  MultipartHttpServletRequest) {
1072:                        logger
1073:                                .debug("Request is already a MultipartHttpServletRequest - if not in a forward, "
1074:                                        + "this typically results from an additional MultipartFilter in web.xml");
1075:                    } else {
1076:                        return this .multipartResolver.resolveMultipart(request);
1077:                    }
1078:                }
1079:                // If not returned before: return original request.
1080:                return request;
1081:            }
1082:
1083:            /**
1084:             * Clean up any resources used by the given multipart request (if any).
1085:             * @param request current HTTP request
1086:             * @see MultipartResolver#cleanupMultipart
1087:             */
1088:            protected void cleanupMultipart(HttpServletRequest request) {
1089:                if (request instanceof  MultipartHttpServletRequest) {
1090:                    this .multipartResolver
1091:                            .cleanupMultipart((MultipartHttpServletRequest) request);
1092:                }
1093:            }
1094:
1095:            /**
1096:             * Return the HandlerExecutionChain for this request.
1097:             * Try all handler mappings in order.
1098:             * @param request current HTTP request
1099:             * @param cache whether to cache the HandlerExecutionChain in a request attribute
1100:             * @return the HandlerExceutionChain, or <code>null</code> if no handler could be found
1101:             */
1102:            protected HandlerExecutionChain getHandler(
1103:                    HttpServletRequest request, boolean cache) throws Exception {
1104:                HandlerExecutionChain handler = (HandlerExecutionChain) request
1105:                        .getAttribute(HANDLER_EXECUTION_CHAIN_ATTRIBUTE);
1106:                if (handler != null) {
1107:                    if (!cache) {
1108:                        request
1109:                                .removeAttribute(HANDLER_EXECUTION_CHAIN_ATTRIBUTE);
1110:                    }
1111:                    return handler;
1112:                }
1113:
1114:                Iterator it = this .handlerMappings.iterator();
1115:                while (it.hasNext()) {
1116:                    HandlerMapping hm = (HandlerMapping) it.next();
1117:                    if (logger.isDebugEnabled()) {
1118:                        logger.debug("Testing handler map [" + hm
1119:                                + "] in DispatcherServlet with name '"
1120:                                + getServletName() + "'");
1121:                    }
1122:                    handler = hm.getHandler(request);
1123:                    if (handler != null) {
1124:                        if (cache) {
1125:                            request.setAttribute(
1126:                                    HANDLER_EXECUTION_CHAIN_ATTRIBUTE, handler);
1127:                        }
1128:                        return handler;
1129:                    }
1130:                }
1131:                return null;
1132:            }
1133:
1134:            /**
1135:             * No handler found -> set appropriate HTTP response status.
1136:             * @param request current HTTP request
1137:             * @param response current HTTP response
1138:             * @throws IOException if thrown by the HttpServletResponse
1139:             */
1140:            protected void noHandlerFound(HttpServletRequest request,
1141:                    HttpServletResponse response) throws IOException {
1142:                if (pageNotFoundLogger.isWarnEnabled()) {
1143:                    String requestUri = new UrlPathHelper()
1144:                            .getRequestUri(request);
1145:                    pageNotFoundLogger.warn("No mapping for [" + requestUri
1146:                            + "] in DispatcherServlet with name '"
1147:                            + getServletName() + "'");
1148:                }
1149:                response.sendError(HttpServletResponse.SC_NOT_FOUND);
1150:            }
1151:
1152:            /**
1153:             * Return the HandlerAdapter for this handler object.
1154:             * @param handler the handler object to find an adapter for
1155:             * @throws ServletException if no HandlerAdapter can be found for the handler.
1156:             * This is a fatal error.
1157:             */
1158:            protected HandlerAdapter getHandlerAdapter(Object handler)
1159:                    throws ServletException {
1160:                Iterator it = this .handlerAdapters.iterator();
1161:                while (it.hasNext()) {
1162:                    HandlerAdapter ha = (HandlerAdapter) it.next();
1163:                    if (logger.isDebugEnabled()) {
1164:                        logger.debug("Testing handler adapter [" + ha + "]");
1165:                    }
1166:                    if (ha.supports(handler)) {
1167:                        return ha;
1168:                    }
1169:                }
1170:                throw new ServletException(
1171:                        "No adapter for handler ["
1172:                                + handler
1173:                                + "]: Does your handler implement a supported interface like Controller?");
1174:            }
1175:
1176:            /**
1177:             * Determine an error ModelAndView via the registered HandlerExceptionResolvers.
1178:             * @param request current HTTP request
1179:             * @param response current HTTP response
1180:             * @param handler the executed handler, or <code>null</code> if none chosen at the time of
1181:             * the exception (for example, if multipart resolution failed)
1182:             * @param ex the exception that got thrown during handler execution
1183:             * @return a corresponding ModelAndView to forward to
1184:             * @throws Exception if no error ModelAndView found
1185:             */
1186:            protected ModelAndView processHandlerException(
1187:                    HttpServletRequest request, HttpServletResponse response,
1188:                    Object handler, Exception ex) throws Exception {
1189:
1190:                ModelAndView exMv = null;
1191:                for (Iterator it = this .handlerExceptionResolvers.iterator(); exMv == null
1192:                        && it.hasNext();) {
1193:                    HandlerExceptionResolver resolver = (HandlerExceptionResolver) it
1194:                            .next();
1195:                    exMv = resolver.resolveException(request, response,
1196:                            handler, ex);
1197:                }
1198:                if (exMv != null) {
1199:                    if (logger.isDebugEnabled()) {
1200:                        logger.debug(
1201:                                "Handler execution resulted in exception - forwarding to resolved error view: "
1202:                                        + exMv, ex);
1203:                    }
1204:                    return exMv;
1205:                } else {
1206:                    throw ex;
1207:                }
1208:            }
1209:
1210:            /**
1211:             * Render the given ModelAndView. This is the last stage in handling a request.
1212:             * It may involve resolving the view by name.
1213:             * @param mv the ModelAndView to render
1214:             * @param request current HTTP servlet request
1215:             * @param response current HTTP servlet response
1216:             * @throws Exception if there's a problem rendering the view
1217:             */
1218:            protected void render(ModelAndView mv, HttpServletRequest request,
1219:                    HttpServletResponse response) throws Exception {
1220:
1221:                // Determine locale for request and apply it to the response.
1222:                Locale locale = this .localeResolver.resolveLocale(request);
1223:                response.setLocale(locale);
1224:
1225:                View view = null;
1226:
1227:                // Do we need view name translation?
1228:                if (!mv.hasView()) {
1229:                    mv.setViewName(getDefaultViewName(request));
1230:                }
1231:
1232:                if (mv.isReference()) {
1233:                    // We need to resolve the view name.
1234:                    view = resolveViewName(mv.getViewName(), mv
1235:                            .getModelInternal(), locale, request);
1236:                    if (view == null) {
1237:                        throw new ServletException(
1238:                                "Could not resolve view with name '"
1239:                                        + mv.getViewName()
1240:                                        + "' in servlet with name '"
1241:                                        + getServletName() + "'");
1242:                    }
1243:                } else {
1244:                    // No need to lookup: the ModelAndView object contains the actual View object.
1245:                    view = mv.getView();
1246:                    if (view == null) {
1247:                        throw new ServletException("ModelAndView [" + mv
1248:                                + "] neither contains a view name nor a "
1249:                                + "View object in servlet with name '"
1250:                                + getServletName() + "'");
1251:                    }
1252:                }
1253:
1254:                // Delegate to the View object for rendering.
1255:                if (logger.isDebugEnabled()) {
1256:                    logger.debug("Rendering view [" + view
1257:                            + "] in DispatcherServlet with name '"
1258:                            + getServletName() + "'");
1259:                }
1260:                view.render(mv.getModelInternal(), request, response);
1261:            }
1262:
1263:            /**
1264:             * Translate the supplied request into a default view name.
1265:             * @param request current HTTP servlet request
1266:             * @return the view name
1267:             * @throws Exception if view name translation failed
1268:             */
1269:            protected String getDefaultViewName(HttpServletRequest request)
1270:                    throws Exception {
1271:                String viewName = this .viewNameTranslator.getViewName(request);
1272:                if (viewName == null) {
1273:                    throw new ServletException("Could not translate request ["
1274:                            + request + "] into view name using ["
1275:                            + this .viewNameTranslator.getClass().getName()
1276:                            + "]");
1277:                }
1278:                return viewName;
1279:            }
1280:
1281:            /**
1282:             * Resolve the given view name into a View object (to be rendered).
1283:             * <p>Default implementations asks all ViewResolvers of this dispatcher.
1284:             * Can be overridden for custom resolution strategies, potentially based
1285:             * on specific model attributes or request parameters.
1286:             * @param viewName the name of the view to resolve
1287:             * @param model the model to be passed to the view
1288:             * @param locale the current locale
1289:             * @param request current HTTP servlet request
1290:             * @return the View object, or <code>null</code> if none found
1291:             * @throws Exception if the view cannot be resolved
1292:             * (typically in case of problems creating an actual View object)
1293:             * @see ViewResolver#resolveViewName
1294:             */
1295:            protected View resolveViewName(String viewName, Map model,
1296:                    Locale locale, HttpServletRequest request) throws Exception {
1297:
1298:                for (Iterator it = this .viewResolvers.iterator(); it.hasNext();) {
1299:                    ViewResolver viewResolver = (ViewResolver) it.next();
1300:                    View view = viewResolver.resolveViewName(viewName, locale);
1301:                    if (view != null) {
1302:                        return view;
1303:                    }
1304:                }
1305:                return null;
1306:            }
1307:
1308:            /**
1309:             * Trigger afterCompletion callbacks on the mapped HandlerInterceptors.
1310:             * Will just invoke afterCompletion for all interceptors whose preHandle
1311:             * invocation has successfully completed and returned true.
1312:             * @param mappedHandler the mapped HandlerExecutionChain
1313:             * @param interceptorIndex index of last interceptor that successfully completed
1314:             * @param ex Exception thrown on handler execution, or <code>null</code> if none
1315:             * @see HandlerInterceptor#afterCompletion
1316:             */
1317:            private void triggerAfterCompletion(
1318:                    HandlerExecutionChain mappedHandler, int interceptorIndex,
1319:                    HttpServletRequest request, HttpServletResponse response,
1320:                    Exception ex) throws Exception {
1321:
1322:                // Apply afterCompletion methods of registered interceptors.
1323:                if (mappedHandler != null) {
1324:                    if (mappedHandler.getInterceptors() != null) {
1325:                        for (int i = interceptorIndex; i >= 0; i--) {
1326:                            HandlerInterceptor interceptor = mappedHandler
1327:                                    .getInterceptors()[i];
1328:                            try {
1329:                                interceptor.afterCompletion(request, response,
1330:                                        mappedHandler.getHandler(), ex);
1331:                            } catch (Throwable ex2) {
1332:                                logger
1333:                                        .error(
1334:                                                "HandlerInterceptor.afterCompletion threw exception",
1335:                                                ex2);
1336:                            }
1337:                        }
1338:                    }
1339:                }
1340:            }
1341:
1342:            /**
1343:             * Restore the request attributes after an include.
1344:             * @param request current HTTP request
1345:             * @param attributesSnapshot the snapshot of the request attributes
1346:             * before the include
1347:             */
1348:            private void restoreAttributesAfterInclude(
1349:                    HttpServletRequest request, Map attributesSnapshot) {
1350:                logger
1351:                        .debug("Restoring snapshot of request attributes after include");
1352:
1353:                // Need to copy into separate Collection here, to avoid side effects
1354:                // on the Enumeration when removing attributes.
1355:                Set attrsToCheck = new HashSet();
1356:                Enumeration attrNames = request.getAttributeNames();
1357:                while (attrNames.hasMoreElements()) {
1358:                    String attrName = (String) attrNames.nextElement();
1359:                    if (this .cleanupAfterInclude
1360:                            || attrName.startsWith(DispatcherServlet.class
1361:                                    .getName())) {
1362:                        attrsToCheck.add(attrName);
1363:                    }
1364:                }
1365:
1366:                // Iterate over the attributes to check, restoring the original value
1367:                // or removing the attribute, respectively, if appropriate.
1368:                for (Iterator it = attrsToCheck.iterator(); it.hasNext();) {
1369:                    String attrName = (String) it.next();
1370:                    Object attrValue = attributesSnapshot.get(attrName);
1371:                    if (attrValue != null) {
1372:                        if (logger.isDebugEnabled()) {
1373:                            logger
1374:                                    .debug("Restoring original value of attribute ["
1375:                                            + attrName + "] after include");
1376:                        }
1377:                        request.setAttribute(attrName, attrValue);
1378:                    } else {
1379:                        if (logger.isDebugEnabled()) {
1380:                            logger.debug("Removing attribute [" + attrName
1381:                                    + "] after include");
1382:                        }
1383:                        request.removeAttribute(attrName);
1384:                    }
1385:                }
1386:            }
1387:
1388:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.