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 848 protected boolean processRoles(HttpServletRequest request, 849 HttpServletResponse response, 850 ActionMapping mapping) 851 throws IOException , ServletException { 852 853 String roles[] = mapping.getRoleNames(); 855 if ((roles == null) || (roles.length < 1)) { 856 return (true); 857 } 858 859 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 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 902 protected boolean processValidate(HttpServletRequest request, 903 HttpServletResponse response, 904 ActionForm form, 905 ActionMapping mapping) 906 throws IOException , ServletException { 907 908 if (form == null) { 909 return (true); 910 } 911 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 if (!mapping.getValidate()) { 921 return (true); 922 } 923 924 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 if (form.getMultipartRequestHandler() != null) { 938 if (log.isTraceEnabled()) { 939 log.trace(" Rolling back multipart request"); 940 } 941 form.getMultipartRequestHandler().rollback(); 942 } 943 944 String 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 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 987 protected void internalModuleRelativeForward( 988 String uri, 989 HttpServletRequest request, 990 HttpServletResponse response) 991 throws IOException , ServletException { 992 993 uri = moduleConfig.getPrefix() + uri; 995 996 if (log.isDebugEnabled()) { 999 log.debug(" Delegating via forward to '" + uri + "'"); 1000 } 1001 doForward(uri, request, response); 1002 } 1003 1004 1005 1018 protected void internalModuleRelativeInclude( 1019 String uri, 1020 HttpServletRequest request, 1021 HttpServletResponse response) 1022 throws IOException , ServletException { 1023 1024 uri = moduleConfig.getPrefix() + uri; 1026 1027 if (log.isDebugEnabled()) { 1030 log.debug(" Delegating via include to '" + uri + "'"); 1031 } 1032 doInclude(uri, request, response); 1033 } 1034 1035 1036 1045 protected void doForward( 1046 String uri, 1047 HttpServletRequest request, 1048 HttpServletResponse response) 1049 throws IOException , ServletException { 1050 1051 if (request instanceof MultipartRequestWrapper) { 1053 request = ((MultipartRequestWrapper) request).getRequest(); 1054 } 1055 1056 RequestDispatcher 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 1076 protected void doInclude( 1077 String uri, 1078 HttpServletRequest request, 1079 HttpServletResponse response) 1080 throws IOException , ServletException { 1081 1082 if (request instanceof MultipartRequestWrapper) { 1084 request = ((MultipartRequestWrapper) request).getRequest(); 1085 } 1086 1087 RequestDispatcher 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 1100 1101 1105 protected MessageResources getInternal() { 1106 1107 return (servlet.getInternal()); 1108 1109 } 1110 1111 1112 1116 protected ServletContext getServletContext() { 1117 1118 return (servlet.getServletContext()); 1119 1120 } 1121 1122 1123 1131 protected void log(String message) { 1132 1134 servlet.log(message); 1135 1136 } 1137 1138 1139 1149 protected void log(String message, Throwable exception) { 1150 1152 servlet.log(message, exception); 1153 1154 } 1155 1156 1157} 1158 | Popular Tags |