Source Code Cross Referenced for MultiActionController.java in  » J2EE » spring-framework-2.0.6 » org » springframework » web » servlet » mvc » multiaction » 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.mvc.multiaction 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright 2002-2007 the original author or authors.
003:         *
004:         * Licensed under the Apache License, Version 2.0 (the "License");
005:         * you may not use this file except in compliance with the License.
006:         * You may obtain a copy of the License at
007:         *
008:         *      http://www.apache.org/licenses/LICENSE-2.0
009:         *
010:         * Unless required by applicable law or agreed to in writing, software
011:         * distributed under the License is distributed on an "AS IS" BASIS,
012:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013:         * See the License for the specific language governing permissions and
014:         * limitations under the License.
015:         */
016:
017:        package org.springframework.web.servlet.mvc.multiaction;
018:
019:        import java.lang.reflect.InvocationTargetException;
020:        import java.lang.reflect.Method;
021:        import java.util.ArrayList;
022:        import java.util.HashMap;
023:        import java.util.List;
024:        import java.util.Map;
025:
026:        import javax.servlet.ServletRequest;
027:        import javax.servlet.http.HttpServletRequest;
028:        import javax.servlet.http.HttpServletResponse;
029:        import javax.servlet.http.HttpSession;
030:
031:        import org.apache.commons.logging.Log;
032:        import org.apache.commons.logging.LogFactory;
033:
034:        import org.springframework.beans.BeanUtils;
035:        import org.springframework.util.Assert;
036:        import org.springframework.validation.ValidationUtils;
037:        import org.springframework.validation.Validator;
038:        import org.springframework.web.HttpSessionRequiredException;
039:        import org.springframework.web.bind.ServletRequestDataBinder;
040:        import org.springframework.web.servlet.ModelAndView;
041:        import org.springframework.web.servlet.mvc.AbstractController;
042:        import org.springframework.web.servlet.mvc.LastModified;
043:        import org.springframework.web.util.NestedServletException;
044:
045:        /**
046:         * Controller implementation that allows multiple request types to be
047:         * handled by the same class. Subclasses of this class can handle several
048:         * different types of request with methods of the form
049:         *
050:         * <pre>
051:         * (ModelAndView | Map | void) actionName(HttpServletRequest request, HttpServletResponse response);</pre>
052:         *
053:         * May take a third parameter HttpSession in which an existing session will be required,
054:         * or a third parameter of an arbitrary class that gets treated as command
055:         * (i.e. an instance of the class gets created, and request parameters get bound to it)
056:         *
057:         * <p>These methods can throw any kind of exception, but should only let propagate
058:         * those that they consider fatal, or which their class or superclass is prepared to
059:         * catch by implementing an exception handler.
060:         *
061:         * <p>When returning just a {@link Map} instance view name translation will be used to generate
062:         * the view name. The configured {@link org.springframework.web.servlet.RequestToViewNameTranslator}
063:         * will be used to determine the view name.
064:         *
065:         * <p>When returning <code>void</code> a return value of <code>null</code> is assumed
066:         * meaning that the handler method is responsible for writing the response directly to
067:         * the supplied {@link HttpServletResponse}.
068:         *
069:         * <p>This model allows for rapid coding, but loses the advantage of compile-time
070:         * checking. It is similar to a Struts 1.1 DispatchAction, but more sophisticated.
071:         * Also supports delegation to another object.
072:         *
073:         * <p>An implementation of the MethodNameResolver interface defined in this package
074:         * should return a method name for a given request, based on any aspect of the request,
075:         * such as its URL or an "action" parameter. The actual strategy can be configured
076:         * via the "methodNameResolver" bean property, for each MultiActionController.
077:         *
078:         * <p>The default MethodNameResolver is InternalPathMethodNameResolver; further included
079:         * strategies are PropertiesMethodNameResolver and ParameterMethodNameResolver.
080:         *
081:         * <p>Subclasses can implement custom exception handler methods with names such as:
082:         *
083:         * <pre>
084:         * ModelAndView anyMeaningfulName(HttpServletRequest request, HttpServletResponse response, ExceptionClass exception);</pre>
085:         *
086:         * The third parameter can be any subclass or Exception or RuntimeException.
087:         *
088:         * <p>There can also be an optional lastModified method for handlers, of signature:
089:         *
090:         * <pre>
091:         * long anyMeaningfulNameLastModified(HttpServletRequest request)</pre>
092:         *
093:         * If such a method is present, it will be invoked. Default return from getLastModified
094:         * is -1, meaning that the content must always be regenerated.
095:         *
096:         * <p>Note that method overloading isn't allowed.
097:         * 
098:         * <p>See also the description of the workflow performed by
099:         * {@link AbstractController the superclass} (in that section of the class
100:         * level Javadoc entitled 'workflow').
101:         *
102:         * <p><b>Note:</b> For maximum data binding flexibility, consider direct usage
103:         * of a ServletRequestDataBinder in your controller method, instead of relying
104:         * on a declared command argument. This allows for full control over the entire
105:         * binder setup and usage, including the invocation of Validators and the
106:         * subsequent evaluation of binding/validation errors.
107:         * 
108:         * @author Rod Johnson
109:         * @author Juergen Hoeller
110:         * @author Colin Sampaleanu
111:         * @author Rob Harrop
112:         * @see MethodNameResolver
113:         * @see InternalPathMethodNameResolver
114:         * @see PropertiesMethodNameResolver
115:         * @see ParameterMethodNameResolver
116:         * @see org.springframework.web.servlet.mvc.LastModified#getLastModified
117:         * @see org.springframework.web.bind.ServletRequestDataBinder
118:         */
119:        public class MultiActionController extends AbstractController implements 
120:                LastModified {
121:
122:            /** Suffix for last-modified methods */
123:            public static final String LAST_MODIFIED_METHOD_SUFFIX = "LastModified";
124:
125:            /** Default command name used for binding command objects: "command" */
126:            public static final String DEFAULT_COMMAND_NAME = "command";
127:
128:            /** Log category to use when no mapped handler is found for a request */
129:            public static final String PAGE_NOT_FOUND_LOG_CATEGORY = "org.springframework.web.servlet.PageNotFound";
130:
131:            /** Additional logger to use when no mapped handler is found for a request */
132:            protected static final Log pageNotFoundLogger = LogFactory
133:                    .getLog(PAGE_NOT_FOUND_LOG_CATEGORY);
134:
135:            /**
136:             * Helper object that knows how to return method names from incoming requests.
137:             * Can be overridden via the methodNameResolver bean property
138:             */
139:            private MethodNameResolver methodNameResolver = new InternalPathMethodNameResolver();
140:
141:            /** List of Validators to apply to commands */
142:            private Validator[] validators;
143:
144:            /** Object we'll invoke methods on. Defaults to this. */
145:            private Object delegate;
146:
147:            /** Methods, keyed by name */
148:            private Map handlerMethodMap = new HashMap();
149:
150:            /** LastModified methods, keyed by handler method name (without LAST_MODIFIED_SUFFIX) */
151:            private Map lastModifiedMethodMap = new HashMap();
152:
153:            /** Methods, keyed by exception class */
154:            private Map exceptionHandlerMap = new HashMap();
155:
156:            /**
157:             * Constructor for MultiActionController that looks for handler methods
158:             * in the present subclass. Caches methods for quick invocation later.
159:             * This class's use of reflection will impose little overhead at runtime.
160:             */
161:            public MultiActionController() {
162:                this .delegate = this ;
163:                registerHandlerMethods(this .delegate);
164:                // We'll accept no handler methods found here - a delegate might be set later on.
165:            }
166:
167:            /**
168:             * Constructor for MultiActionController that looks for handler methods in delegate,
169:             * rather than a subclass of this class. Caches methods for quick invocation later.
170:             * @param delegate handler object. This doesn't need to implement any particular
171:             * interface, as everything is done using reflection.
172:             */
173:            public MultiActionController(Object delegate) {
174:                setDelegate(delegate);
175:            }
176:
177:            /**
178:             * Set the method name resolver that this class should use.
179:             * Allows parameterization of handler method mappings.
180:             */
181:            public final void setMethodNameResolver(
182:                    MethodNameResolver methodNameResolver) {
183:                this .methodNameResolver = methodNameResolver;
184:            }
185:
186:            /**
187:             * Return the MethodNameResolver used by this class.
188:             */
189:            public final MethodNameResolver getMethodNameResolver() {
190:                return this .methodNameResolver;
191:            }
192:
193:            /**
194:             * Set the Validators for this controller.
195:             * The Validator must support the specified command class.
196:             */
197:            public final void setValidators(Validator[] validators) {
198:                this .validators = validators;
199:            }
200:
201:            /**
202:             * Return the Validators for this controller.
203:             */
204:            public final Validator[] getValidators() {
205:                return validators;
206:            }
207:
208:            /**
209:             * Set the delegate used by this class. The default is <code>this</code>,
210:             * assuming that handler methods have been added by a subclass.
211:             * <p>This method does not get invoked once the class is configured.
212:             * @param delegate an object containing handler methods
213:             */
214:            public final void setDelegate(Object delegate) {
215:                Assert.notNull(delegate, "Delegate must not be null");
216:                this .delegate = delegate;
217:                registerHandlerMethods(this .delegate);
218:                // There must be SOME handler methods.
219:                if (this .handlerMethodMap.isEmpty()) {
220:                    throw new IllegalStateException(
221:                            "No handler methods in class ["
222:                                    + this .delegate.getClass() + "]");
223:                }
224:            }
225:
226:            /**
227:             * Registers all handlers methods on the delegate object.
228:             */
229:            private void registerHandlerMethods(Object delegate) {
230:                this .handlerMethodMap.clear();
231:                this .lastModifiedMethodMap.clear();
232:                this .exceptionHandlerMap.clear();
233:
234:                // Look at all methods in the subclass, trying to find
235:                // methods that are validators according to our criteria
236:                Method[] methods = delegate.getClass().getMethods();
237:                for (int i = 0; i < methods.length; i++) {
238:                    // We're looking for methods with given parameters.
239:                    Method method = methods[i];
240:                    if (isExceptionHandlerMethod(method)) {
241:                        registerExceptionHandlerMethod(method);
242:                    } else if (isHandlerMethod(method)) {
243:                        registerHandlerMethod(method);
244:                        registerLastModifiedMethodIfExists(delegate, method);
245:                    }
246:                }
247:            }
248:
249:            /**
250:             * Is the supplied method a valid handler method?
251:             * <p>Does not consider <code>Controller.handleRequest</code> itself
252:             * as handler method (to avoid potential stack overflow).
253:             */
254:            private boolean isHandlerMethod(Method method) {
255:                Class returnType = method.getReturnType();
256:                if (ModelAndView.class.equals(returnType)
257:                        || Map.class.equals(returnType)
258:                        || void.class.equals(returnType)) {
259:                    Class[] parameterTypes = method.getParameterTypes();
260:                    return (parameterTypes.length >= 2
261:                            && HttpServletRequest.class
262:                                    .equals(parameterTypes[0])
263:                            && HttpServletResponse.class
264:                                    .equals(parameterTypes[1]) && !("handleRequest"
265:                            .equals(method.getName()) && parameterTypes.length == 2));
266:                }
267:                return false;
268:            }
269:
270:            /**
271:             * Is the supplied method a valid exception handler method?
272:             */
273:            private boolean isExceptionHandlerMethod(Method method) {
274:                return (isHandlerMethod(method)
275:                        && method.getParameterTypes().length == 3 && Throwable.class
276:                        .isAssignableFrom(method.getParameterTypes()[2]));
277:            }
278:
279:            /**
280:             * Registers the supplied method as a request handler.
281:             */
282:            private void registerHandlerMethod(Method method) {
283:                if (logger.isDebugEnabled()) {
284:                    logger.debug("Found action method [" + method + "]");
285:                }
286:                this .handlerMethodMap.put(method.getName(), method);
287:            }
288:
289:            /**
290:             * Registers a LastModified handler method for the supplied handler method
291:             * if one exists.
292:             */
293:            private void registerLastModifiedMethodIfExists(Object delegate,
294:                    Method method) {
295:                // Look for corresponding LastModified method.
296:                try {
297:                    Method lastModifiedMethod = delegate.getClass().getMethod(
298:                            method.getName() + LAST_MODIFIED_METHOD_SUFFIX,
299:                            new Class[] { HttpServletRequest.class });
300:                    // Put in cache, keyed by handler method name.
301:                    this .lastModifiedMethodMap.put(method.getName(),
302:                            lastModifiedMethod);
303:                    if (logger.isDebugEnabled()) {
304:                        logger
305:                                .debug("Found last modified method for action method ["
306:                                        + method + "]");
307:                    }
308:                } catch (NoSuchMethodException ex) {
309:                    // No last modified method. That's ok.
310:                }
311:            }
312:
313:            /**
314:             * Registers the supplied method as an exception handler.
315:             */
316:            private void registerExceptionHandlerMethod(Method method) {
317:                this .exceptionHandlerMap.put(method.getParameterTypes()[2],
318:                        method);
319:                if (logger.isDebugEnabled()) {
320:                    logger.debug("Found exception handler method [" + method
321:                            + "]");
322:                }
323:            }
324:
325:            //---------------------------------------------------------------------
326:            // Implementation of LastModified
327:            //---------------------------------------------------------------------
328:
329:            /**
330:             * Try to find an XXXXLastModified method, where XXXX is the name of a handler.
331:             * Return -1, indicating that content must be updated, if there's no such handler.
332:             * @see org.springframework.web.servlet.mvc.LastModified#getLastModified(HttpServletRequest)
333:             */
334:            public long getLastModified(HttpServletRequest request) {
335:                try {
336:                    String handlerMethodName = this .methodNameResolver
337:                            .getHandlerMethodName(request);
338:                    Method lastModifiedMethod = (Method) this .lastModifiedMethodMap
339:                            .get(handlerMethodName);
340:                    if (lastModifiedMethod != null) {
341:                        try {
342:                            // invoke the last-modified method
343:                            Long wrappedLong = (Long) lastModifiedMethod
344:                                    .invoke(this .delegate,
345:                                            new Object[] { request });
346:                            return wrappedLong.longValue();
347:                        } catch (Exception ex) {
348:                            // We encountered an error invoking the last-modified method.
349:                            // We can't do anything useful except log this, as we can't throw an exception.
350:                            logger
351:                                    .error(
352:                                            "Failed to invoke last-modified method",
353:                                            ex);
354:                        }
355:                    } // if we had a lastModified method for this request
356:                } catch (NoSuchRequestHandlingMethodException ex) {
357:                    // No handler method for this request. This shouldn't happen, as this
358:                    // method shouldn't be called unless a previous invocation of this class
359:                    // has generated content. Do nothing, that's OK: We'll return default.
360:                }
361:                return -1L;
362:            }
363:
364:            //---------------------------------------------------------------------
365:            // Implementation of AbstractController
366:            //---------------------------------------------------------------------
367:
368:            /**
369:             * Determine a handler method and invoke it.
370:             * @see MethodNameResolver#getHandlerMethodName
371:             * @see #invokeNamedMethod
372:             * @see #handleNoSuchRequestHandlingMethod
373:             */
374:            protected ModelAndView handleRequestInternal(
375:                    HttpServletRequest request, HttpServletResponse response)
376:                    throws Exception {
377:                try {
378:                    String methodName = this .methodNameResolver
379:                            .getHandlerMethodName(request);
380:                    return invokeNamedMethod(methodName, request, response);
381:                } catch (NoSuchRequestHandlingMethodException ex) {
382:                    return handleNoSuchRequestHandlingMethod(ex, request,
383:                            response);
384:                }
385:            }
386:
387:            /**
388:             * Handle the case where no request handler method was found.
389:             * <p>The default implementation logs a warning and sends an HTTP 404 error.
390:             * Alternatively, a fallback view could be chosen, or the
391:             * NoSuchRequestHandlingMethodException could be rethrown as-is.
392:             * @param ex the NoSuchRequestHandlingMethodException to be handled
393:             * @param request current HTTP request
394:             * @param response current HTTP response
395:             * @return a ModelAndView to render, or <code>null</code> if handled directly
396:             * @throws Exception an Exception that should be thrown as result of the servlet request
397:             */
398:            protected ModelAndView handleNoSuchRequestHandlingMethod(
399:                    NoSuchRequestHandlingMethodException ex,
400:                    HttpServletRequest request, HttpServletResponse response)
401:                    throws Exception {
402:
403:                pageNotFoundLogger.warn(ex.getMessage());
404:                response.sendError(HttpServletResponse.SC_NOT_FOUND);
405:                return null;
406:            }
407:
408:            /**
409:             * Invokes the named method.
410:             * <p>Uses a custom exception handler if possible; otherwise, throw an
411:             * unchecked exception; wrap a checked exception or Throwable.
412:             */
413:            protected final ModelAndView invokeNamedMethod(String methodName,
414:                    HttpServletRequest request, HttpServletResponse response)
415:                    throws Exception {
416:
417:                Method method = (Method) this .handlerMethodMap.get(methodName);
418:                if (method == null) {
419:                    throw new NoSuchRequestHandlingMethodException(methodName,
420:                            getClass());
421:                }
422:
423:                try {
424:                    List params = new ArrayList(4);
425:                    params.add(request);
426:                    params.add(response);
427:
428:                    if (method.getParameterTypes().length >= 3
429:                            && method.getParameterTypes()[2]
430:                                    .equals(HttpSession.class)) {
431:                        HttpSession session = request.getSession(false);
432:                        if (session == null) {
433:                            throw new HttpSessionRequiredException(
434:                                    "Pre-existing session required for handler method '"
435:                                            + methodName + "'");
436:                        }
437:                        params.add(session);
438:                    }
439:
440:                    // If last parameter isn't of HttpSession type, it's a command.
441:                    if (method.getParameterTypes().length >= 3
442:                            && !method.getParameterTypes()[method
443:                                    .getParameterTypes().length - 1]
444:                                    .equals(HttpSession.class)) {
445:                        Object command = newCommandObject(method
446:                                .getParameterTypes()[method.getParameterTypes().length - 1]);
447:                        params.add(command);
448:                        bind(request, command);
449:                    }
450:
451:                    Object returnValue = method.invoke(this .delegate, params
452:                            .toArray(new Object[params.size()]));
453:                    return massageReturnValueIfNecessary(returnValue);
454:                } catch (InvocationTargetException ex) {
455:                    // The handler method threw an exception.
456:                    return handleException(request, response, ex
457:                            .getTargetException());
458:                } catch (Exception ex) {
459:                    // The binding process threw an exception.
460:                    return handleException(request, response, ex);
461:                }
462:            }
463:
464:            /**
465:             * Processes the return value of a handler method to ensure that it either returns
466:             * <code>null</code> or an instance of {@link ModelAndView}. When returning a {@link Map},
467:             * the {@link Map} instance is wrapped in a new {@link ModelAndView} instance.
468:             */
469:            private ModelAndView massageReturnValueIfNecessary(
470:                    Object returnValue) {
471:                if (returnValue instanceof  ModelAndView) {
472:                    return (ModelAndView) returnValue;
473:                } else if (returnValue instanceof  Map) {
474:                    return new ModelAndView().addAllObjects((Map) returnValue);
475:                } else {
476:                    // Either returned null or was 'void' return.
477:                    // We'll assume that the handle method already wrote the response.
478:                    return null;
479:                }
480:            }
481:
482:            /**
483:             * Create a new command object of the given class.
484:             * <p>This implementation uses <code>BeanUtils.instantiateClass</code>,
485:             * so commands need to have public no-arg constructors.
486:             * Subclasses can override this implementation if desired.
487:             * @throws Exception if the command object could not be instantiated
488:             * @see org.springframework.beans.BeanUtils#instantiateClass(Class)
489:             */
490:            protected Object newCommandObject(Class clazz) throws Exception {
491:                if (logger.isDebugEnabled()) {
492:                    logger.debug("Must create new command of class ["
493:                            + clazz.getName() + "]");
494:                }
495:                return BeanUtils.instantiateClass(clazz);
496:            }
497:
498:            /**
499:             * Bind request parameters onto the given command bean
500:             * @param request request from which parameters will be bound
501:             * @param command command object, that must be a JavaBean
502:             * @throws Exception in case of invalid state or arguments
503:             */
504:            protected void bind(HttpServletRequest request, Object command)
505:                    throws Exception {
506:                logger
507:                        .debug("Binding request parameters onto MultiActionController command");
508:                ServletRequestDataBinder binder = createBinder(request, command);
509:                binder.bind(request);
510:                if (this .validators != null) {
511:                    for (int i = 0; i < this .validators.length; i++) {
512:                        if (this .validators[i].supports(command.getClass())) {
513:                            ValidationUtils.invokeValidator(this .validators[i],
514:                                    command, binder.getBindingResult());
515:                        }
516:                    }
517:                }
518:                binder.closeNoCatch();
519:            }
520:
521:            /**
522:             * Create a new binder instance for the given command and request.
523:             * <p>Called by <code>bind</code>. Can be overridden to plug in custom
524:             * ServletRequestDataBinder subclasses.
525:             * <p>Default implementation creates a standard ServletRequestDataBinder,
526:             * and invokes <code>initBinder</code>. Note that <code>initBinder</code>
527:             * will not be invoked if you override this method!
528:             * @param request current HTTP request
529:             * @param command the command to bind onto
530:             * @return the new binder instance
531:             * @throws Exception in case of invalid state or arguments
532:             * @see #bind
533:             * @see #initBinder
534:             */
535:            protected ServletRequestDataBinder createBinder(
536:                    HttpServletRequest request, Object command)
537:                    throws Exception {
538:
539:                ServletRequestDataBinder binder = new ServletRequestDataBinder(
540:                        command, getCommandName(command));
541:                initBinder(request, binder);
542:                return binder;
543:            }
544:
545:            /**
546:             * Return the command name to use for the given command object.
547:             * Default is "command".
548:             * @param command the command object
549:             * @return the command name to use
550:             * @see #DEFAULT_COMMAND_NAME
551:             */
552:            protected String getCommandName(Object command) {
553:                return DEFAULT_COMMAND_NAME;
554:            }
555:
556:            /**
557:             * Initialize the given binder instance, for example with custom editors.
558:             * Called by <code>createBinder</code>.
559:             * <p>This method allows you to register custom editors for certain fields of your
560:             * command class. For instance, you will be able to transform Date objects into a
561:             * String pattern and back, in order to allow your JavaBeans to have Date properties
562:             * and still be able to set and display them in an HTML interface.
563:             * <p>Default implementation is empty.
564:             * <p>Note: the command object is not directly passed to this method, but it's available
565:             * via {@link org.springframework.validation.DataBinder#getTarget()}
566:             * @param request current HTTP request
567:             * @param binder new binder instance
568:             * @throws Exception in case of invalid state or arguments
569:             * @see #createBinder
570:             * @see org.springframework.validation.DataBinder#registerCustomEditor
571:             * @see org.springframework.beans.propertyeditors.CustomDateEditor
572:             */
573:            protected void initBinder(HttpServletRequest request,
574:                    ServletRequestDataBinder binder) throws Exception {
575:
576:                initBinder((ServletRequest) request, binder);
577:            }
578:
579:            /**
580:             * Initialize the given binder instance, for example with custom editors.
581:             * @deprecated since Spring 2.0:
582:             * use <code>initBinder(HttpServletRequest, ServletRequestDataBinder) instead
583:             */
584:            protected void initBinder(ServletRequest request,
585:                    ServletRequestDataBinder binder) throws Exception {
586:            }
587:
588:            /**
589:             * Determine the exception handler method for the given exception.
590:             * Can return null if not found.
591:             * @return a handler for the given exception type, or <code>null</code>
592:             * @param exception the exception to handle
593:             */
594:            protected Method getExceptionHandler(Throwable exception) {
595:                Class exceptionClass = exception.getClass();
596:                if (logger.isDebugEnabled()) {
597:                    logger.debug("Trying to find handler for exception class ["
598:                            + exceptionClass.getName() + "]");
599:                }
600:                Method handler = (Method) this .exceptionHandlerMap
601:                        .get(exceptionClass);
602:                while (handler == null
603:                        && !exceptionClass.equals(Throwable.class)) {
604:                    if (logger.isDebugEnabled()) {
605:                        logger
606:                                .debug("Trying to find handler for exception superclass ["
607:                                        + exceptionClass.getName() + "]");
608:                    }
609:                    exceptionClass = exceptionClass.getSuperclass();
610:                    handler = (Method) this .exceptionHandlerMap
611:                            .get(exceptionClass);
612:                }
613:                return handler;
614:            }
615:
616:            /**
617:             * We've encountered an exception which may be recoverable
618:             * (InvocationTargetException or HttpSessionRequiredException).
619:             * Allow the subclass a chance to handle it.
620:             * @param request current HTTP request
621:             * @param response current HTTP response
622:             * @param ex the exception that got thrown
623:             * @return a ModelAndView to render the response
624:             */
625:            private ModelAndView handleException(HttpServletRequest request,
626:                    HttpServletResponse response, Throwable ex)
627:                    throws Exception {
628:
629:                Method handler = getExceptionHandler(ex);
630:                if (handler != null) {
631:                    return invokeExceptionHandler(handler, request, response,
632:                            ex);
633:                }
634:                // If we get here, there was no custom handler
635:                if (ex instanceof  Exception) {
636:                    throw (Exception) ex;
637:                }
638:                if (ex instanceof  Error) {
639:                    throw (Error) ex;
640:                }
641:                // Should never happen!
642:                throw new NestedServletException(
643:                        "Unknown Throwable type encountered", ex);
644:            }
645:
646:            /**
647:             * Invoke the selected exception handler.
648:             * @param handler handler method to invoke
649:             */
650:            private ModelAndView invokeExceptionHandler(Method handler,
651:                    HttpServletRequest request, HttpServletResponse response,
652:                    Throwable ex) throws Exception {
653:
654:                if (handler == null) {
655:                    throw new NestedServletException(
656:                            "No handler for exception", ex);
657:                }
658:
659:                // If we get here, we have a handler.
660:                if (logger.isDebugEnabled()) {
661:                    logger.debug("Invoking exception handler [" + handler
662:                            + "] for exception [" + ex + "]");
663:                }
664:                try {
665:                    Object returnValue = handler.invoke(this .delegate,
666:                            new Object[] { request, response, ex });
667:                    return massageReturnValueIfNecessary(returnValue);
668:                } catch (InvocationTargetException ex2) {
669:                    Throwable targetEx = ex2.getTargetException();
670:                    if (targetEx instanceof  Exception) {
671:                        throw (Exception) targetEx;
672:                    }
673:                    if (targetEx instanceof  Error) {
674:                        throw (Error) targetEx;
675:                    }
676:                    // Should never happen!
677:                    throw new NestedServletException(
678:                            "Unknown Throwable type encountered", targetEx);
679:                }
680:            }
681:
682:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.