| 1 18 19 package org.apache.struts.action; 20 21 import java.io.IOException ; 22 import java.util.HashMap ; 23 import java.util.Iterator ; 24 import java.util.Locale ; 25 26 import javax.servlet.RequestDispatcher ; 27 import javax.servlet.ServletContext ; 28 import javax.servlet.ServletException ; 29 import javax.servlet.http.HttpServletRequest ; 30 import javax.servlet.http.HttpServletResponse ; 31 import javax.servlet.http.HttpSession ; 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 55 public class RequestProcessor { 56 57 58 60 61 65 public static final String INCLUDE_PATH_INFO = 66 "javax.servlet.include.path_info"; 67 68 69 73 public static final String INCLUDE_SERVLET_PATH = 74 "javax.servlet.include.servlet_path"; 75 76 77 79 80 85 protected HashMap actions = new HashMap (); 86 87 88 91 protected ModuleConfig moduleConfig = null; 92 93 94 97 protected static Log log = LogFactory.getLog(RequestProcessor.class); 98 99 100 103 protected ActionServlet servlet = null; 104 105 106 108 109 112 public void destroy() { 113 114 synchronized (this.actions) { 115 Iterator 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 134 public void init(ActionServlet servlet, 135 ModuleConfig moduleConfig) 136 throws ServletException { 137 138 synchronized (actions) { 139 actions.clear(); 140 } 141 142 this.servlet = servlet; 143 this.moduleConfig = moduleConfig; 144 } 145 146 147 158 public void process(HttpServletRequest request, 159 HttpServletResponse response) 160 throws IOException , ServletException { 161 162 request = processMultipart(request); 164 165 String 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 processLocale(request, response); 178 179 processContent(request, response); 181 processNoCache(request, response); 182 183 if (!processPreprocess(request, response)) { 185 return; 186 } 187 188 this.processCachedMessages(request, response); 189 190 ActionMapping mapping = processMapping(request, response, path); 192 if (mapping == null) { 193 return; 194 } 195 196 if (!processRoles(request, response, mapping)) { 198 return; 199 } 200 201 ActionForm form = processActionForm(request, response, mapping); 203 processPopulate(request, response, form, mapping); 204 if (!processValidate(request, response, form, mapping)) { 205 return; 206 } 207 208 if (!processForward(request, response, mapping)) { 210 return; 211 } 212 213 if (!processInclude(request, response, mapping)) { 214 return; 215 } 216 217 Action action = processActionCreate(request, response, mapping); 219 if (action == null) { 220 return; 221 } 222 223 ActionForward forward = 225 processActionPerform(request, response, 226 action, form, mapping); 227 228 processForwardConfig(request, response, forward); 230 231 } 232 233 234 236 237 247 protected Action processActionCreate(HttpServletRequest request, 248 HttpServletResponse response, 249 ActionMapping mapping) 250 throws IOException { 251 252 String className = mapping.getType(); 254 if (log.isDebugEnabled()) { 255 log.debug(" Looking for Action instance for class " + className); 256 } 257 258 262 Action instance = null; 263 synchronized (actions) { 264 265 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 if (log.isTraceEnabled()) { 276 log.trace(" Creating new Action instance"); 277 } 278 279 try { 280 instance = (Action) RequestUtils.applicationInstance(className); 281 } catch (Exception 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 314 protected ActionForm processActionForm(HttpServletRequest request, 315 HttpServletResponse response, 316 ActionMapping mapping) { 317 318 ActionForm instance = RequestUtils.createActionForm 320 (request, mapping, moduleConfig, servlet); 321 if (instance == null) { 322 return (null); 323 } 324 325 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 session = request.getSession(); 335 session.setAttribute(mapping.getAttribute(), instance); 336 } 337 return (instance); 338 339 } 340 341 342 354 protected void processForwardConfig(HttpServletRequest request, 355 HttpServletResponse response, 356 ForwardConfig forward) 357 throws IOException , ServletException { 358 359 if (forward == null) { 360 return; 361 } 362 363 if (log.isDebugEnabled()) { 364 log.debug("processForwardConfig(" + forward + ")"); 365 } 366 367 String forwardPath = forward.getPath(); 368 String uri = null; 369 370 if (forwardPath.startsWith("/")) { 373 uri = RequestUtils.forwardURL(request, forward, null); } else { 375 uri = forwardPath; 376 } 377 378 if (forward.getRedirect()) { 379 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 395 410 protected ActionForward 411 processActionPerform(HttpServletRequest request, 412 HttpServletResponse response, 413 Action action, 414 ActionForm form, 415 ActionMapping mapping) 416 throws IOException , ServletException { 417 418 try { 419 return (action.execute(mapping, form, request, response)); 420 } catch (Exception e) { 421 return (processException(request, response, 422 e, form, mapping)); 423 } 424 425 } 426 427 439 protected void processCachedMessages( 440 441 HttpServletRequest request, 442 HttpServletResponse response) { 443 444 HttpSession session = request.getSession(false); 445 if (session == null) { 446 return; 447 } 448 449 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 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 481 protected void processContent(HttpServletRequest request, 482 HttpServletResponse response) { 483 484 String contentType = moduleConfig.getControllerConfig().getContentType(); 485 if (contentType != null) { 486 response.setContentType(contentType); 487 } 488 489 } 490 491 492 506 protected ActionForward processException(HttpServletRequest request, 507 HttpServletResponse response, 508 Exception exception, 509 ActionForm form, 510 ActionMapping mapping) 511 throws IOException , ServletException { 512 513 ExceptionConfig config = mapping.findException(exception.getClass()); 515 if (config == null) { 516 log.warn(getInternal().getMessage("unhandledException", 517 exception.getClass())); 518 if (exception instanceof IOException ) { 519 throw (IOException ) exception; 520 } else if (exception instanceof ServletException ) { 521 throw (ServletException ) exception; 522 } else { 523 throw new ServletException (exception); 524 } 525 } 526 527 try { 529 ExceptionHandler handler = (ExceptionHandler) 530 RequestUtils.applicationInstance(config.getHandler()); 531 return (handler.execute(exception, config, mapping, form, 532 request, response)); 533 } catch (Exception e) { 534 throw new ServletException (e); 535 } 536 537 } 538 539 540 549 protected boolean processForward(HttpServletRequest request, 550 HttpServletResponse response, 551 ActionMapping mapping) 552 throws IOException , ServletException { 553 554 String 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 575 protected boolean processInclude(HttpServletRequest request, 576 HttpServletResponse response, 577 ActionMapping mapping) 578 throws IOException , ServletException { 579 580 String 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 600 protected void processLocale(HttpServletRequest request, 601 HttpServletResponse response) { 602 603 if (!moduleConfig.getControllerConfig().getLocale()) { 605 return; 606 } 607 608 HttpSession session = request.getSession(); 610 if (session.getAttribute(Globals.LOCALE_KEY) != null) { 611 return; 612 } 613 614 Locale 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 637 protected ActionMapping processMapping(HttpServletRequest request, 638 HttpServletResponse response, 639 String path) 640 throws IOException { 641 642 ActionMapping mapping = (ActionMapping) 644 moduleConfig.findActionConfig(path); 645 646 if (mapping != null) { 648 request.setAttribute(Globals.MAPPING_KEY, mapping); 649 return (mapping); 650 } 651 652 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 String 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 677 protected HttpServletRequest processMultipart(HttpServletRequest request) { 678 679 if (!"POST".equalsIgnoreCase(request.getMethod())) { 680 return (request); 681 } 682 683 String 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 703 protected void processNoCache(HttpServletRequest request, 704 HttpServletResponse 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 726 protected String processPath(HttpServletRequest request, 727 HttpServletResponse response) 728 throws IOException { 729 730 String path = null; 731 732 path = (String ) 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 path = (String ) request.getAttribute(INCLUDE_SERVLET_PATH); 743 if (path == null) { 744 path = request.getServletPath(); 745 } 746 String prefix = moduleConfig.getPrefix(); 747 if (!path.startsWith(prefix)) { 748 String 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 782 protected void processPopulate(HttpServletRequest request, 783 HttpServletResponse response, 784 ActionForm form, 785 ActionMapping mapping) 786 throws ServletException { 787 788 if (form == null) { 789 return; 790 } 791 792 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 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 827 protected boolean processPreprocess(HttpServletRequest request, 828 HttpServletResponse response) { 829 830 return (true); 831 832 } 833 834 835 |