KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > struts > action > RequestProcessor


1 /*
2  * $Id: RequestProcessor.java 164530 2005-04-25 03:11:07Z niallp $
3  *
4  * Copyright 2000-2005 The Apache Software Foundation.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */

18
19 package org.apache.struts.action;
20
21 import java.io.IOException JavaDoc;
22 import java.util.HashMap JavaDoc;
23 import java.util.Iterator JavaDoc;
24 import java.util.Locale JavaDoc;
25
26 import javax.servlet.RequestDispatcher JavaDoc;
27 import javax.servlet.ServletContext JavaDoc;
28 import javax.servlet.ServletException JavaDoc;
29 import javax.servlet.http.HttpServletRequest JavaDoc;
30 import javax.servlet.http.HttpServletResponse JavaDoc;
31 import javax.servlet.http.HttpSession JavaDoc;
32
33 import org.apache.commons.logging.Log;
34 import org.apache.commons.logging.LogFactory;
35 import org.apache.struts.Globals;
36 import org.apache.struts.config.ActionConfig;
37 import org.apache.struts.config.ExceptionConfig;
38 import org.apache.struts.config.ForwardConfig;
39 import org.apache.struts.config.ModuleConfig;
40 import org.apache.struts.taglib.html.Constants;
41 import org.apache.struts.upload.MultipartRequestWrapper;
42 import org.apache.struts.util.MessageResources;
43 import org.apache.struts.util.RequestUtils;
44
45 /**
46  * <p><strong>RequestProcessor</strong> contains the processing logic that
47  * the {@link ActionServlet} performs as it receives each servlet request
48  * from the container. You can customize the request processing behavior by
49  * subclassing this class and overriding the method(s) whose behavior you are
50  * interested in changing.</p>
51  *
52  * @version $Rev: 164530 $ $Date: 2005-04-25 04:11:07 +0100 (Mon, 25 Apr 2005) $
53  * @since Struts 1.1
54  */

55 public class RequestProcessor {
56
57
58     // ----------------------------------------------------- Manifest Constants
59

60
61     /**
62      * <p>The request attribute under which the path information is stored for
63      * processing during a <code>RequestDispatcher.include</code> call.</p>
64      */

65     public static final String JavaDoc INCLUDE_PATH_INFO =
66         "javax.servlet.include.path_info";
67
68
69     /**
70      * <p>The request attribute under which the servlet path information is stored
71      * for processing during a <code>RequestDispatcher.include</code> call.</p>
72      */

73     public static final String JavaDoc INCLUDE_SERVLET_PATH =
74         "javax.servlet.include.servlet_path";
75
76
77     // ----------------------------------------------------- Instance Variables
78

79
80     /**
81      * <p>The set of <code>Action</code> instances that have been created and
82      * initialized, keyed by the fully qualified Java class name of the
83      * <code>Action</code> class.</p>
84      */

85     protected HashMap JavaDoc actions = new HashMap JavaDoc();
86
87
88     /**
89      * <p>The <code>ModuleConfiguration</code> with which we are associated.</p>
90      */

91     protected ModuleConfig moduleConfig = null;
92
93
94     /**
95      * <p>Commons Logging instance.</p>
96      */

97     protected static Log log = LogFactory.getLog(RequestProcessor.class);
98
99
100     /**
101      * <p>The servlet with which we are associated.</p>
102      */

103     protected ActionServlet servlet = null;
104
105
106     // --------------------------------------------------------- Public Methods
107

108
109     /**
110      * <p>Clean up in preparation for a shutdown of this application.</p>
111      */

112     public void destroy() {
113
114         synchronized (this.actions) {
115             Iterator JavaDoc actions = this.actions.values().iterator();
116             while (actions.hasNext()) {
117                 Action action = (Action) actions.next();
118                 action.setServlet(null);
119             }
120             this.actions.clear();
121         }
122         this.servlet = null;
123
124     }
125
126
127     /**
128      * <p>Initialize this request processor instance.</p>
129      *
130      * @param servlet The ActionServlet we are associated with
131      * @param moduleConfig The ModuleConfig we are associated with.
132      * @throws ServletException If an error occor during initialization
133      */

134     public void init(ActionServlet servlet,
135                      ModuleConfig moduleConfig)
136            throws ServletException JavaDoc {
137
138         synchronized (actions) {
139             actions.clear();
140         }
141         
142         this.servlet = servlet;
143         this.moduleConfig = moduleConfig;
144     }
145
146
147     /**
148      * <p>Process an <code>HttpServletRequest</code> and create the
149      * corresponding <code>HttpServletResponse</code> or dispatch
150      * to another resource.</p>
151      *
152      * @param request The servlet request we are processing
153      * @param response The servlet response we are creating
154      *
155      * @exception IOException if an input/output error occurs
156      * @exception ServletException if a processing exception occurs
157      */

158     public void process(HttpServletRequest JavaDoc request,
159                         HttpServletResponse JavaDoc response)
160         throws IOException JavaDoc, ServletException JavaDoc {
161
162         // Wrap multipart requests with a special wrapper
163
request = processMultipart(request);
164
165         // Identify the path component we will use to select a mapping
166
String JavaDoc path = processPath(request, response);
167         if (path == null) {
168             return;
169         }
170         
171         if (log.isDebugEnabled()) {
172             log.debug("Processing a '" + request.getMethod() +
173                       "' for path '" + path + "'");
174         }
175
176         // Select a Locale for the current user if requested
177
processLocale(request, response);
178
179         // Set the content type and no-caching headers if requested
180
processContent(request, response);
181         processNoCache(request, response);
182
183         // General purpose preprocessing hook
184
if (!processPreprocess(request, response)) {
185             return;
186         }
187         
188         this.processCachedMessages(request, response);
189
190         // Identify the mapping for this request
191
ActionMapping mapping = processMapping(request, response, path);
192         if (mapping == null) {
193             return;
194         }
195
196         // Check for any role required to perform this action
197
if (!processRoles(request, response, mapping)) {
198             return;
199         }
200
201         // Process any ActionForm bean related to this request
202
ActionForm form = processActionForm(request, response, mapping);
203         processPopulate(request, response, form, mapping);
204         if (!processValidate(request, response, form, mapping)) {
205             return;
206         }
207
208         // Process a forward or include specified by this mapping
209
if (!processForward(request, response, mapping)) {
210             return;
211         }
212         
213         if (!processInclude(request, response, mapping)) {
214             return;
215         }
216
217         // Create or acquire the Action instance to process this request
218
Action action = processActionCreate(request, response, mapping);
219         if (action == null) {
220             return;
221         }
222
223         // Call the Action instance itself
224
ActionForward forward =
225             processActionPerform(request, response,
226                                  action, form, mapping);
227
228         // Process the returned ActionForward instance
229
processForwardConfig(request, response, forward);
230
231     }
232
233
234     // ----------------------------------------------------- Processing Methods
235

236
237     /**
238      * <p>Return an <code>Action</code> instance that will be used to process
239      * the current request, creating a new one if necessary.</p>
240      *
241      * @param request The servlet request we are processing
242      * @param response The servlet response we are creating
243      * @param mapping The mapping we are using
244      *
245      * @exception IOException if an input/output error occurs
246      */

247     protected Action processActionCreate(HttpServletRequest JavaDoc request,
248                                          HttpServletResponse JavaDoc response,
249                                          ActionMapping mapping)
250         throws IOException JavaDoc {
251
252         // Acquire the Action instance we will be using (if there is one)
253
String JavaDoc className = mapping.getType();
254         if (log.isDebugEnabled()) {
255             log.debug(" Looking for Action instance for class " + className);
256         }
257
258         // :TODO: If there were a mapping property indicating whether
259
// an Action were a singleton or not ([true]),
260
// could we just instantiate and return a new instance here?
261

262         Action instance = null;
263         synchronized (actions) {
264
265             // Return any existing Action instance of this class
266
instance = (Action) actions.get(className);
267             if (instance != null) {
268                 if (log.isTraceEnabled()) {
269                     log.trace(" Returning existing Action instance");
270                 }
271                 return (instance);
272             }
273
274             // Create and return a new Action instance
275
if (log.isTraceEnabled()) {
276                 log.trace(" Creating new Action instance");
277             }
278             
279             try {
280                 instance = (Action) RequestUtils.applicationInstance(className);
281                 // :TODO: Maybe we should propagate this exception
282
// instead of returning null.
283
} catch (Exception JavaDoc e) {
284                 log.error(
285                     getInternal().getMessage("actionCreate", mapping.getPath()),
286                     e);
287                     
288                 response.sendError(
289                     HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
290                     getInternal().getMessage("actionCreate", mapping.getPath()));
291                     
292                 return (null);
293             }
294             
295             instance.setServlet(this.servlet);
296             actions.put(className, instance);
297         }
298
299         return (instance);
300
301     }
302
303
304     /**
305      * <p>Retrieve and return the <code>ActionForm</code> associated with
306      * this mapping, creating and retaining one if necessary. If there is no
307      * <code>ActionForm</code> associated with this mapping, return
308      * <code>null</code>.</p>
309      *
310      * @param request The servlet request we are processing
311      * @param response The servlet response we are creating
312      * @param mapping The mapping we are using
313      */

314     protected ActionForm processActionForm(HttpServletRequest JavaDoc request,
315                                            HttpServletResponse JavaDoc response,
316                                            ActionMapping mapping) {
317
318         // Create (if necessary) a form bean to use
319
ActionForm instance = RequestUtils.createActionForm
320             (request, mapping, moduleConfig, servlet);
321         if (instance == null) {
322             return (null);
323         }
324
325         // Store the new instance in the appropriate scope
326
if (log.isDebugEnabled()) {
327             log.debug(" Storing ActionForm bean instance in scope '" +
328                 mapping.getScope() + "' under attribute key '" +
329                 mapping.getAttribute() + "'");
330         }
331         if ("request".equals(mapping.getScope())) {
332             request.setAttribute(mapping.getAttribute(), instance);
333         } else {
334             HttpSession JavaDoc session = request.getSession();
335             session.setAttribute(mapping.getAttribute(), instance);
336         }
337         return (instance);
338
339     }
340
341
342     /**
343      * <p>Forward or redirect to the specified destination, by the specified
344      * mechanism. This method uses a <code>ForwardConfig</code> object instead
345      * an <code>ActionForward</code>.</p>
346      *
347      * @param request The servlet request we are processing
348      * @param response The servlet response we are creating
349      * @param forward The ForwardConfig controlling where we go next
350      *
351      * @exception IOException if an input/output error occurs
352      * @exception ServletException if a servlet exception occurs
353      */

354     protected void processForwardConfig(HttpServletRequest JavaDoc request,
355                                         HttpServletResponse JavaDoc response,
356                                         ForwardConfig forward)
357         throws IOException JavaDoc, ServletException JavaDoc {
358
359         if (forward == null) {
360             return;
361         }
362         
363         if (log.isDebugEnabled()) {
364             log.debug("processForwardConfig(" + forward + ")");
365         }
366         
367         String JavaDoc forwardPath = forward.getPath();
368         String JavaDoc uri = null;
369         
370         // paths not starting with / should be passed through without any processing
371
// (ie. they're absolute)
372
if (forwardPath.startsWith("/")) {
373             uri = RequestUtils.forwardURL(request, forward, null); // get module relative uri
374
} else {
375             uri = forwardPath;
376         }
377         
378         if (forward.getRedirect()) {
379             // only prepend context path for relative uri
380
if (uri.startsWith("/")) {
381                 uri = request.getContextPath() + uri;
382             }
383             response.sendRedirect(response.encodeRedirectURL(uri));
384             
385         } else {
386             doForward(uri, request, response);
387         }
388
389     }
390
391
392     // :FIXME: if Action.execute throws Exception, and Action.process has been removed,
393
// should the process* methods still throw IOException, ServletException?
394

395     /**
396      * <P>Ask the specified <code>Action</code> instance to handle this
397      * request. Return the <code>ActionForward</code> instance (if any)
398      * returned by the called <code>Action</code> for further processing.
399      * </P>
400      *
401      * @param request The servlet request we are processing
402      * @param response The servlet response we are creating
403      * @param action The Action instance to be used
404      * @param form The ActionForm instance to pass to this Action
405      * @param mapping The ActionMapping instance to pass to this Action
406      *
407      * @exception IOException if an input/output error occurs
408      * @exception ServletException if a servlet exception occurs
409      */

410     protected ActionForward
411         processActionPerform(HttpServletRequest JavaDoc request,
412                              HttpServletResponse JavaDoc response,
413                              Action action,
414                              ActionForm form,
415                              ActionMapping mapping)
416         throws IOException JavaDoc, ServletException JavaDoc {
417
418         try {
419             return (action.execute(mapping, form, request, response));
420         } catch (Exception JavaDoc e) {
421             return (processException(request, response,
422                                      e, form, mapping));
423         }
424
425     }
426     
427     /**
428      * <p>Removes any <code>ActionMessages</code> object stored in the session
429      * under <code>Globals.MESSAGE_KEY</code> and <code>Globals.ERROR_KEY</code>
430      * if the messages' <code>isAccessed</code> method returns true. This
431      * allows messages to be stored in the session, display one time, and be
432      * released here.</p>
433      *
434      * @param request The servlet request we are processing.
435      * @param response The servlet response we are creating.
436      *
437      * @since Struts 1.2
438      */

439     protected void processCachedMessages(
440
441         HttpServletRequest JavaDoc request,
442         HttpServletResponse JavaDoc response) {
443
444         HttpSession JavaDoc session = request.getSession(false);
445         if (session == null) {
446             return;
447         }
448
449         // Remove messages as needed
450
ActionMessages messages =
451             (ActionMessages) session.getAttribute(Globals.MESSAGE_KEY);
452
453         if (messages != null) {
454             if (messages.isAccessed()) {
455                 session.removeAttribute(Globals.MESSAGE_KEY);
456             }
457         }
458         
459         // Remove error messages as needed
460
messages = (ActionMessages) session.getAttribute(Globals.ERROR_KEY);
461
462         if (messages != null) {
463             if (messages.isAccessed()) {
464                 session.removeAttribute(Globals.ERROR_KEY);
465             }
466         }
467         
468     }
469
470
471     /**
472      * <p>Set the default content type (with optional character encoding) for
473      * all responses if requested. <strong>NOTE</strong> - This header will
474      * be overridden automatically if a
475      * <code>RequestDispatcher.forward</code> call is
476      * ultimately invoked.</p>
477      *
478      * @param request The servlet request we are processing
479      * @param response The servlet response we are creating
480      */

481     protected void processContent(HttpServletRequest JavaDoc request,
482                                   HttpServletResponse JavaDoc response) {
483
484         String JavaDoc contentType = moduleConfig.getControllerConfig().getContentType();
485         if (contentType != null) {
486             response.setContentType(contentType);
487         }
488
489     }
490
491
492     /**
493      * <p>Ask our exception handler to handle the exception. Return the
494      * <code>ActionForward</code> instance (if any) returned by the
495      * called <code>ExceptionHandler</code>.</p>
496      *
497      * @param request The servlet request we are processing
498      * @param response The servlet response we are processing
499      * @param exception The exception being handled
500      * @param form The ActionForm we are processing
501      * @param mapping The ActionMapping we are using
502      *
503      * @exception IOException if an input/output error occurs
504      * @exception ServletException if a servlet exception occurs
505      */

506     protected ActionForward processException(HttpServletRequest JavaDoc request,
507                                              HttpServletResponse JavaDoc response,
508                                              Exception JavaDoc exception,
509                                              ActionForm form,
510                                              ActionMapping mapping)
511         throws IOException JavaDoc, ServletException JavaDoc {
512
513         // Is there a defined handler for this exception?
514
ExceptionConfig config = mapping.findException(exception.getClass());
515         if (config == null) {
516             log.warn(getInternal().getMessage("unhandledException",
517                                               exception.getClass()));
518             if (exception instanceof IOException JavaDoc) {
519                 throw (IOException JavaDoc) exception;
520             } else if (exception instanceof ServletException JavaDoc) {
521                 throw (ServletException JavaDoc) exception;
522             } else {
523                 throw new ServletException JavaDoc(exception);
524             }
525         }
526
527         // Use the configured exception handling
528
try {
529             ExceptionHandler handler = (ExceptionHandler)
530             RequestUtils.applicationInstance(config.getHandler());
531             return (handler.execute(exception, config, mapping, form,
532                                     request, response));
533         } catch (Exception JavaDoc e) {
534             throw new ServletException JavaDoc(e);
535         }
536
537     }
538
539
540     /**
541      * <p>Process a forward requested by this mapping (if any). Return
542      * <code>true</code> if standard processing should continue, or
543      * <code>false</code> if we have already handled this request.</p>
544      *
545      * @param request The servlet request we are processing
546      * @param response The servlet response we are creating
547      * @param mapping The ActionMapping we are using
548      */

549     protected boolean processForward(HttpServletRequest JavaDoc request,
550                                      HttpServletResponse JavaDoc response,
551                                      ActionMapping mapping)
552         throws IOException JavaDoc, ServletException JavaDoc {
553
554         // Are we going to processing this request?
555
String JavaDoc forward = mapping.getForward();
556         if (forward == null) {
557             return (true);
558         }
559
560         internalModuleRelativeForward(forward, request, response);
561         return (false);
562
563     }
564
565
566     /**
567      * <p>Process an include requested by this mapping (if any). Return
568      * <code>true</code> if standard processing should continue, or
569      * <code>false</code> if we have already handled this request.</p>
570      *
571      * @param request The servlet request we are processing
572      * @param response The servlet response we are creating
573      * @param mapping The ActionMapping we are using
574      */

575     protected boolean processInclude(HttpServletRequest JavaDoc request,
576                                      HttpServletResponse JavaDoc response,
577                                      ActionMapping mapping)
578         throws IOException JavaDoc, ServletException JavaDoc {
579
580         // Are we going to processing this request?
581
String JavaDoc include = mapping.getInclude();
582         if (include == null) {
583             return (true);
584         }
585
586         internalModuleRelativeInclude(include, request, response);
587         return (false);
588
589     }
590
591
592     /**
593      * <p>Automatically select a <code>Locale</code> for the current user, if requested.
594      * <strong>NOTE</strong> - configuring Locale selection will trigger
595      * the creation of a new <code>HttpSession</code> if necessary.</p>
596      *
597      * @param request The servlet request we are processing
598      * @param response The servlet response we are creating
599      */

600     protected void processLocale(HttpServletRequest JavaDoc request,
601                                  HttpServletResponse JavaDoc response) {
602
603         // Are we configured to select the Locale automatically?
604
if (!moduleConfig.getControllerConfig().getLocale()) {
605             return;
606         }
607
608         // Has a Locale already been selected?
609
HttpSession JavaDoc session = request.getSession();
610         if (session.getAttribute(Globals.LOCALE_KEY) != null) {
611             return;
612         }
613
614         // Use the Locale returned by the servlet container (if any)
615
Locale JavaDoc locale = request.getLocale();
616         if (locale != null) {
617             if (log.isDebugEnabled()) {
618                 log.debug(" Setting user locale '" + locale + "'");
619             }
620             session.setAttribute(Globals.LOCALE_KEY, locale);
621         }
622
623     }
624
625
626     /**
627      * <p>Select the mapping used to process the selection path for this request.
628      * If no mapping can be identified, create an error response and return
629      * <code>null</code>.</p>
630      *
631      * @param request The servlet request we are processing
632      * @param response The servlet response we are creating
633      * @param path The portion of the request URI for selecting a mapping
634      *
635      * @exception IOException if an input/output error occurs
636      */

637     protected ActionMapping processMapping(HttpServletRequest JavaDoc request,
638                                            HttpServletResponse JavaDoc response,
639                                            String JavaDoc path)
640         throws IOException JavaDoc {
641
642         // Is there a mapping for this path?
643
ActionMapping mapping = (ActionMapping)
644             moduleConfig.findActionConfig(path);
645
646         // If a mapping is found, put it in the request and return it
647
if (mapping != null) {
648             request.setAttribute(Globals.MAPPING_KEY, mapping);
649             return (mapping);
650         }
651
652         // Locate the mapping for unknown paths (if any)
653
ActionConfig configs[] = moduleConfig.findActionConfigs();
654         for (int i = 0; i < configs.length; i++) {
655             if (configs[i].getUnknown()) {
656                 mapping = (ActionMapping) configs[i];
657                 request.setAttribute(Globals.MAPPING_KEY, mapping);
658                 return (mapping);
659             }
660         }
661
662         // No mapping can be found to process this request
663
String JavaDoc msg = getInternal().getMessage("processInvalid", path);
664         log.error(msg);
665         response.sendError(HttpServletResponse.SC_NOT_FOUND, msg);
666         
667         return null;
668     }
669
670
671     /**
672      * <p>If this is a multipart request, wrap it with a special wrapper.
673      * Otherwise, return the request unchanged.</p>
674      *
675      * @param request The HttpServletRequest we are processing
676      */

677     protected HttpServletRequest JavaDoc processMultipart(HttpServletRequest JavaDoc request) {
678
679         if (!"POST".equalsIgnoreCase(request.getMethod())) {
680             return (request);
681         }
682         
683         String JavaDoc contentType = request.getContentType();
684         if ((contentType != null) &&
685             contentType.startsWith("multipart/form-data")) {
686             return (new MultipartRequestWrapper(request));
687         } else {
688             return (request);
689         }
690
691     }
692
693
694     /**
695      * <p>Set the no-cache headers for all responses, if requested.
696      * <strong>NOTE</strong> - This header will be overridden
697      * automatically if a <code>RequestDispatcher.forward</code> call is
698      * ultimately invoked.</p>
699      *
700      * @param request The servlet request we are processing
701      * @param response The servlet response we are creating
702      */

703     protected void processNoCache(HttpServletRequest JavaDoc request,
704                                   HttpServletResponse JavaDoc response) {
705
706         if (moduleConfig.getControllerConfig().getNocache()) {
707             response.setHeader("Pragma", "No-cache");
708             response.setHeader("Cache-Control", "no-cache,no-store,max-age=0");
709             response.setDateHeader("Expires", 1);
710         }
711
712     }
713
714
715     /**
716      * <p>Identify and return the path component (from the request URI) that
717      * we will use to select an <code>ActionMapping</code> with which to dispatch.
718      * If no such path can be identified, create an error response and return
719      * <code>null</code>.</p>
720      *
721      * @param request The servlet request we are processing
722      * @param response The servlet response we are creating
723      *
724      * @exception IOException if an input/output error occurs
725      */

726     protected String JavaDoc processPath(HttpServletRequest JavaDoc request,
727                                  HttpServletResponse JavaDoc response)
728         throws IOException JavaDoc {
729
730         String JavaDoc path = null;
731
732         // For prefix matching, match on the path info (if any)
733
path = (String JavaDoc) request.getAttribute(INCLUDE_PATH_INFO);
734         if (path == null) {
735             path = request.getPathInfo();
736         }
737         if ((path != null) && (path.length() > 0)) {
738             return (path);
739         }
740
741         // For extension matching, strip the module prefix and extension
742
path = (String JavaDoc) request.getAttribute(INCLUDE_SERVLET_PATH);
743         if (path == null) {
744             path = request.getServletPath();
745         }
746         String JavaDoc prefix = moduleConfig.getPrefix();
747         if (!path.startsWith(prefix)) {
748             String JavaDoc msg =
749                 getInternal().getMessage("processPath", request.getRequestURI());
750             
751             log.error(msg);
752             response.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
753
754             return null;
755         }
756         
757         path = path.substring(prefix.length());
758         int slash = path.lastIndexOf("/");
759         int period = path.lastIndexOf(".");
760         if ((period >= 0) && (period > slash)) {
761             path = path.substring(0, period);
762         }
763         return (path);
764
765     }
766
767
768     /**
769      * <p>Populate the properties of the specified <code>ActionForm</code> instance from
770      * the request parameters included with this request. In addition,
771      * request attribute <code>Globals.CANCEL_KEY</code> will be set if
772      * the request was submitted with a button created by
773      * <code>CancelTag</code>.</p>
774      *
775      * @param request The servlet request we are processing
776      * @param response The servlet response we are creating
777      * @param form The ActionForm instance we are populating
778      * @param mapping The ActionMapping we are using
779      *
780      * @exception ServletException if thrown by RequestUtils.populate()
781      */

782     protected void processPopulate(HttpServletRequest JavaDoc request,
783                                    HttpServletResponse JavaDoc response,
784                                    ActionForm form,
785                                    ActionMapping mapping)
786         throws ServletException JavaDoc {
787
788         if (form == null) {
789             return;
790         }
791
792         // Populate the bean properties of this ActionForm instance
793
if (log.isDebugEnabled()) {
794             log.debug(" Populating bean properties from this request");
795         }
796         
797         form.setServlet(this.servlet);
798         form.reset(mapping, request);
799         
800         if (mapping.getMultipartClass() != null) {
801             request.setAttribute(Globals.MULTIPART_KEY,
802                                  mapping.getMultipartClass());
803         }
804         
805         RequestUtils.populate(form, mapping.getPrefix(), mapping.getSuffix(),
806                               request);
807
808         // Set the cancellation request attribute if appropriate
809
if ((request.getParameter(Constants.CANCEL_PROPERTY) != null) ||
810             (request.getParameter(Constants.CANCEL_PROPERTY_X) != null)) {
811                 
812             request.setAttribute(Globals.CANCEL_KEY, Boolean.TRUE);
813         }
814
815     }
816
817
818     /**
819      * <p>General-purpose preprocessing hook that can be overridden as required
820      * by subclasses. Return <code>true</code> if you want standard processing
821      * to continue, or <code>false</code> if the response has already been
822      * completed. The default implementation does nothing.</p>
823      *
824      * @param request The servlet request we are processing
825      * @param response The servlet response we are creating
826      */

827     protected boolean processPreprocess(HttpServletRequest JavaDoc request,
828                                         HttpServletResponse JavaDoc response) {
829
830         return (true);
831
832     }
833
834
835     /**
836      * <p>If this action is protected by security roles, make sure that the
837      * current user possesses at least one of them. Return <code>true</code>
838      * to continue normal processing, or <code>false</code> if an appropriate
839      * response has been created and processing should terminate.</p>
840      *
841      * @param request The servlet request we are processing
842      * @param response The servlet response we are creating
843      * @param mapping The mapping we are using
844      *
845      * @exception IOException if an input/output error occurs
846      * @exception ServletException if a servlet exception occurs
847      */

848     protected boolean processRoles(HttpServletRequest JavaDoc request,
849                                    HttpServletResponse JavaDoc response,
850                                    ActionMapping mapping)
851         throws IOException JavaDoc, ServletException JavaDoc {
852
853         // Is this action protected by role requirements?
854
String JavaDoc roles[] = mapping.getRoleNames();
855         if ((roles == null) || (roles.length < 1)) {
856             return (true);
857         }
858
859         // Check the current user against the list of required roles
860
for (int i = 0; i < roles.length; i++) {
861             if (request.isUserInRole(roles[i])) {
862                 if (log.isDebugEnabled()) {
863                     log.debug(" User '" + request.getRemoteUser() +
864                         "' has role '" + roles[i] + "', granting access");
865                 }
866                 return (true);
867             }
868         }
869
870         // The current user is not authorized for this action
871
if (log.isDebugEnabled()) {
872             log.debug(" User '" + request.getRemoteUser() +
873                       "' does not have any required role, denying access");
874         }
875         
876         response.sendError(
877             HttpServletResponse.SC_FORBIDDEN,
878             getInternal().getMessage("notAuthorized", mapping.getPath()));
879                                                     
880         return (false);
881
882     }
883
884
885     /**
886      * <p>If this request was not cancelled, and the request's
887      * {@link ActionMapping} has not disabled validation, call the
888      * <code>validate</code> method of the specified {@link ActionForm},
889      * and forward to the input path if there were any errors.
890      * Return <code>true</code> if we should continue processing,
891      * or <code>false</code> if we have already forwarded control back
892      * to the input form.</p>
893      *
894      * @param request The servlet request we are processing
895      * @param response The servlet response we are creating
896      * @param form The ActionForm instance we are populating
897      * @param mapping The ActionMapping we are using
898      *
899      * @exception IOException if an input/output error occurs
900      * @exception ServletException if a servlet exception occurs
901      */

902     protected boolean processValidate(HttpServletRequest JavaDoc request,
903                                       HttpServletResponse JavaDoc response,
904                                       ActionForm form,
905                                       ActionMapping mapping)
906         throws IOException JavaDoc, ServletException JavaDoc {
907
908         if (form == null) {
909             return (true);
910         }
911                                               // Was this request cancelled?
912
if (request.getAttribute(Globals.CANCEL_KEY) != null) {
913             if (log.isDebugEnabled()) {
914                 log.debug(" Cancelled transaction, skipping validation");
915             }
916             return (true);
917         }
918
919         // Has validation been turned off for this mapping?
920
if (!mapping.getValidate()) {
921             return (true);
922         }
923
924         // Call the form bean's validation method
925
if (log.isDebugEnabled()) {
926             log.debug(" Validating input form properties");
927         }
928         ActionMessages errors = form.validate(mapping, request);
929         if ((errors == null) || errors.isEmpty()) {
930             if (log.isTraceEnabled()) {
931                 log.trace(" No errors detected, accepting input");
932             }
933             return (true);
934         }
935
936         // Special handling for multipart request
937
if (form.getMultipartRequestHandler() != null) {
938             if (log.isTraceEnabled()) {
939                 log.trace(" Rolling back multipart request");
940             }
941             form.getMultipartRequestHandler().rollback();
942         }
943
944         // Was an input path (or forward) specified for this mapping?
945
String JavaDoc input = mapping.getInput();
946         if (input == null) {
947             if (log.isTraceEnabled()) {
948                 log.trace(" Validation failed but no input form available");
949             }
950             response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
951                                getInternal().getMessage("noInput",
952                                                         mapping.getPath()));
953             return (false);
954         }
955
956         // Save our error messages and return to the input form if possible
957
if (log.isDebugEnabled()) {
958             log.debug(" Validation failed, returning to '" + input + "'");
959         }
960         request.setAttribute(Globals.ERROR_KEY, errors);
961
962         if (moduleConfig.getControllerConfig().getInputForward()) {
963             ForwardConfig forward = mapping.findForward(input);
964             processForwardConfig( request, response, forward);
965         } else {
966             internalModuleRelativeForward(input, request, response);
967         }
968
969         return (false);
970
971     }
972
973
974     /**
975      * <p>Do a module relative forward to specified URI using request dispatcher.
976      * URI is relative to the current module. The real URI is compute by prefixing
977      * the module name.</p>
978      * <p>This method is used internally and is not part of the public API. It is
979      * advised to not use it in subclasses. </p>
980      *
981      * @param uri Module-relative URI to forward to
982      * @param request Current page request
983      * @param response Current page response
984      *
985      * @since Struts 1.1
986      */

987     protected void internalModuleRelativeForward(
988         String JavaDoc uri,
989         HttpServletRequest JavaDoc request,
990         HttpServletResponse JavaDoc response)
991         throws IOException JavaDoc, ServletException JavaDoc {
992             
993         // Construct a request dispatcher for the specified path
994
uri = moduleConfig.getPrefix() + uri;
995
996         // Delegate the processing of this request
997
// :FIXME: - exception handling?
998
if (log.isDebugEnabled()) {
999             log.debug(" Delegating via forward to '" + uri + "'");
1000        }
1001        doForward(uri, request, response);
1002    }
1003
1004
1005    /**
1006     * <p>Do a module relative include to specified URI using request dispatcher.
1007     * URI is relative to the current module. The real URI is compute by prefixing
1008     * the module name.</p>
1009     * <p>This method is used internally and is not part of the public API. It is
1010     * advised to not use it in subclasses.</p>
1011     *
1012     * @param uri Module-relative URI to include
1013     * @param request Current page request
1014     * @param response Current page response
1015     *
1016     * @since Struts 1.1
1017     */

1018    protected void internalModuleRelativeInclude(
1019        String JavaDoc uri,
1020        HttpServletRequest JavaDoc request,
1021        HttpServletResponse JavaDoc response)
1022        throws IOException JavaDoc, ServletException JavaDoc {
1023            
1024        // Construct a request dispatcher for the specified path
1025
uri = moduleConfig.getPrefix() + uri;
1026
1027        // Delegate the processing of this request
1028
// FIXME - exception handling?
1029
if (log.isDebugEnabled()) {
1030            log.debug(" Delegating via include to '" + uri + "'");
1031        }
1032        doInclude(uri, request, response);
1033    }
1034
1035
1036    /**
1037     * <p>Do a forward to specified URI using a <code>RequestDispatcher</code>.
1038     * This method is used by all internal method needing to do a forward.</p>
1039     *
1040     * @param uri Context-relative URI to forward to
1041     * @param request Current page request
1042     * @param response Current page response
1043     * @since Struts 1.1
1044     */

1045    protected void doForward(
1046        String JavaDoc uri,
1047        HttpServletRequest JavaDoc request,
1048        HttpServletResponse JavaDoc response)
1049        throws IOException JavaDoc, ServletException JavaDoc {
1050            
1051        // Unwrap the multipart request, if there is one.
1052
if (request instanceof MultipartRequestWrapper) {
1053            request = ((MultipartRequestWrapper) request).getRequest();
1054        }
1055
1056        RequestDispatcher JavaDoc rd = getServletContext().getRequestDispatcher(uri);
1057        if (rd == null) {
1058            response.sendError(
1059                HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
1060                getInternal().getMessage("requestDispatcher", uri));
1061            return;
1062        }
1063        rd.forward(request, response);
1064    }
1065
1066
1067    /**
1068     * <p>Do an include of specified URI using a <code>RequestDispatcher</code>.
1069     * This method is used by all internal method needing to do an include.</p>
1070     *
1071     * @param uri Context-relative URI to include
1072     * @param request Current page request
1073     * @param response Current page response
1074     * @since Struts 1.1
1075     */

1076    protected void doInclude(
1077        String JavaDoc uri,
1078        HttpServletRequest JavaDoc request,
1079        HttpServletResponse JavaDoc response)
1080        throws IOException JavaDoc, ServletException JavaDoc {
1081            
1082        // Unwrap the multipart request, if there is one.
1083
if (request instanceof MultipartRequestWrapper) {
1084            request = ((MultipartRequestWrapper) request).getRequest();
1085        }
1086
1087        RequestDispatcher JavaDoc rd = getServletContext().getRequestDispatcher(uri);
1088        if (rd == null) {
1089            response.sendError(
1090                HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
1091                getInternal().getMessage("requestDispatcher", uri));
1092            return;
1093        }
1094        rd.include(request, response);
1095    }
1096
1097
1098    // -------------------------------------------------------- Support Methods
1099

1100
1101    /**
1102     * <p>Return the <code>MessageResources</code> instance containing our
1103     * internal message strings.</p>
1104     */

1105    protected MessageResources getInternal() {
1106
1107        return (servlet.getInternal());
1108
1109    }
1110
1111
1112    /**
1113     * <p>Return the <code>ServletContext</code> for the web application in which
1114     * we are running.
1115     */

1116    protected ServletContext JavaDoc getServletContext() {
1117
1118        return (servlet.getServletContext());
1119
1120    }
1121
1122
1123    /**
1124     * <p>Log the specified message to the servlet context log for this
1125     * web application.</p>
1126     *
1127     * @param message The message to be logged
1128     * @deprecated Use commons-logging instead. This will be removed in a release
1129     * after Struts 1.2.
1130     */

1131    protected void log(String JavaDoc message) {
1132        // :TODO: Remove after Struts 1.2
1133

1134        servlet.log(message);
1135
1136    }
1137
1138
1139    /**
1140     * <p>Log the specified message and exception to the servlet context log
1141     * for this web application.</p>
1142     *
1143     * @param message The message to be logged
1144     * @param exception The exception to be logged
1145
1146     * @deprecated Use commons-logging instead. This will be removed in a release
1147     * after Struts 1.2.
1148     */

1149    protected void log(String JavaDoc message, Throwable JavaDoc exception) {
1150        // :TODO: Remove after Sruts 1.2
1151

1152        servlet.log(message, exception);
1153
1154    }
1155
1156
1157}
1158
Popular Tags