1 64 65 package com.jcorporate.expresso.core.controller; 66 67 68 import com.jcorporate.expresso.core.ExpressoConstants; 69 import com.jcorporate.expresso.core.ExpressoSchema; 70 import com.jcorporate.expresso.core.controller.session.PersistentSession; 71 import com.jcorporate.expresso.core.db.DBException; 72 import com.jcorporate.expresso.core.dbobj.Schema; 73 import com.jcorporate.expresso.core.dbobj.SchemaFactory; 74 import com.jcorporate.expresso.core.i18n.Messages; 75 import com.jcorporate.expresso.core.jsdkapi.GenericDispatcher; 76 import com.jcorporate.expresso.core.misc.ConfigManager; 77 import com.jcorporate.expresso.core.misc.ConfigurationException; 78 import com.jcorporate.expresso.core.misc.DateTime; 79 import com.jcorporate.expresso.core.misc.EventHandler; 80 import com.jcorporate.expresso.core.misc.SerializableString; 81 import com.jcorporate.expresso.core.misc.StringUtil; 82 import com.jcorporate.expresso.core.security.DelayThread; 83 import com.jcorporate.expresso.core.security.User; 84 import com.jcorporate.expresso.core.servlet.CheckLogin; 85 import com.jcorporate.expresso.kernel.util.ClassLocator; 86 import com.jcorporate.expresso.kernel.util.FastStringBuffer; 87 import com.jcorporate.expresso.services.dbobj.ControllerSecurity; 88 import com.jcorporate.expresso.services.dbobj.RegistrationDomain; 89 import com.jcorporate.expresso.services.dbobj.Setup; 90 import org.apache.commons.beanutils.BeanUtils; 91 import org.apache.log4j.Logger; 92 import org.apache.struts.Globals; 93 import org.apache.struts.action.Action; 94 import org.apache.struts.action.ActionForm; 95 import org.apache.struts.action.ActionForward; 96 import org.apache.struts.action.ActionMapping; 97 import org.apache.struts.config.ActionConfig; 98 import org.apache.struts.config.ForwardConfig; 99 import org.apache.struts.upload.MultipartRequestHandler; 100 101 import javax.servlet.ServletException ; 102 import javax.servlet.http.HttpServletRequest ; 103 import javax.servlet.http.HttpServletResponse ; 104 import java.io.ByteArrayOutputStream ; 105 import java.io.IOException ; 106 import java.io.PrintStream ; 107 import java.io.Serializable ; 108 import java.lang.reflect.InvocationTargetException ; 109 import java.lang.reflect.Method ; 110 import java.util.ArrayList ; 111 import java.util.Enumeration ; 112 import java.util.Hashtable ; 113 import java.util.Iterator ; 114 import java.util.Locale ; 115 import java.util.Stack ; 116 import java.util.Vector ; 117 118 119 150 public abstract class Controller 151 extends Action 152 implements Serializable { 153 156 private static Logger log = Logger.getLogger(Controller.class); 157 158 162 protected Logger mLog = null; 163 164 167 public final static String RESPONSE_KEY = ExpressoConstants.CONTROLLER_RESPONSE_KEY; 168 171 public final static String ORIGINAL_URL_KEY = ExpressoConstants.CONTROLLER_ORIGINAL_URL_KEY; 172 175 public final static String REQUEST_KEY = ExpressoConstants.CONTROLLER_REQUEST_KEY; 176 177 180 public final static String NEWSTATE_EXCEPTION_KEY = ExpressoConstants.NEWSTATE_EXCEPTION_KEY; 181 182 183 public final static String CTL_SUCC_TRAN = "controllerSuccessReturn"; 185 public final static String CTL_SUCC_CTL = "controllerSuccessReturnController"; 186 public final static String CTL_SUCC_STATE = "controllerSuccessReturnState"; 187 public final static String STATE_SUCC_TRAN = "stateSuccessReturn"; 188 public final static String STATE_SUCC_CTL = "stateSuccessReturnController"; 189 public final static String STATE_SUCC_STATE = "stateSuccessReturnState"; 190 public final static String STATE_ERR_TRAN = "stateErrorReturn"; 191 public final static String STATE_ERR_CTL = "stateErrorReturnController"; 192 public final static String STATE_ERR_STATE = "stateErrorReturnState"; 193 public final static String RETURN_TO_SENDER_TRAN = "returnToSender"; 194 195 196 199 public static final String STATE_PARAM_KEY = "state"; 200 201 204 public static final String CONTROLLER_PARAM_KEY = "controller"; 205 206 207 208 private static Hashtable initialStates = new Hashtable (); 209 210 213 private static Hashtable schemas = new Hashtable (); 214 215 216 221 private static Hashtable states = new Hashtable (); 222 223 224 228 private static final Class [] newStateParams = { 229 java.lang.String .class, 230 com.jcorporate.expresso.core.controller.ControllerRequest.class 231 }; 232 233 234 237 private static final Class [] stateHandlerParams = { 238 com.jcorporate.expresso.core.controller.ControllerRequest.class, 239 com.jcorporate.expresso.core.controller.ControllerResponse.class 240 }; 241 242 245 private static final Class [] servletStateHandlerParams = { 246 com.jcorporate.expresso.core.controller.ServletControllerRequest.class, 247 com.jcorporate.expresso.core.controller.ControllerResponse.class 248 }; 249 250 251 264 private ArrayList promptStates = new ArrayList (3); 265 266 267 280 private ArrayList handleStates = new ArrayList (3); 281 282 private State finalState; 283 284 private Transition controllerChainingTransition = null; 285 286 private Transition controllerSecurityTransition = null; 287 288 289 292 public Controller() { 293 294 } 295 296 297 306 protected void addFinalState(State newFinalState) 307 throws NonHandleableException { 308 if (promptStates.contains(newFinalState) || 309 handleStates.contains(newFinalState)) { 310 throw new NonHandleableException("Final state must not be the same as any of the paired states."); 311 } 312 313 314 finalState = newFinalState; 315 addState(newFinalState); 316 317 318 if (StringUtil.notNull(getInitialState()).equals("")) { 320 setInitialState(newFinalState.getName()); 321 } 322 } 323 324 337 protected void addPromptTransitions(State nextState, 338 ControllerResponse response) 339 throws ControllerException { 340 341 342 if (isPromptState(nextState)) { 344 String previousPromptState = previousPromptState(nextState); 345 346 347 if (previousPromptState != null) { 348 Transition previousTransition = new Transition(); 349 previousTransition.setControllerObject(getClass().getName()); 350 previousTransition.setState(previousPromptState); 351 previousTransition.setName("previous"); 352 previousTransition.setLabel("Previous"); 353 response.addTransition(previousTransition); 354 } 355 356 357 Transition nextTransition = null; 359 String nextPromptState = nextPromptState(nextState); 360 361 362 if (nextPromptState != null) { String nextHandleState = nextHandleState(nextState); 364 365 366 nextTransition = new Transition(); 372 nextTransition.setControllerObject(getClass().getName()); 373 nextTransition.setState(nextHandleState); 374 nextTransition.setName("next"); 375 nextTransition.setLabel("Next"); 376 nextTransition.addParam(STATE_SUCC_STATE, nextPromptState); nextTransition.addParam(STATE_SUCC_CTL, 378 response.getControllerClass()); 379 } else { State finalState = getFinalState(); 381 382 383 if (finalState == null) { 384 throw new ControllerException("Final state must exist."); 385 } 386 387 388 nextTransition = new Transition(); 389 nextTransition.setControllerObject(getClass().getName()); 390 nextTransition.setState(finalState.getName()); 391 nextTransition.setName("next"); 392 nextTransition.setLabel(finalState.getDescription()); 393 } 394 395 396 response.addTransition(nextTransition); 397 } 398 } 399 400 407 protected void addState(State newState) { 408 try { 409 newState.setController(this); 410 } catch (ControllerException ce) { 411 log.error("Unable to set controller", ce); 412 } 413 414 415 Hashtable myStateList = (Hashtable ) states.get(getClass().getName()); 416 417 418 if (myStateList == null) { 419 myStateList = new Hashtable (); 420 states.put(getClass().getName(), myStateList); 421 } 422 423 424 myStateList.put(newState.getName(), newState); 425 } 426 427 428 438 protected void addStatePairing(State promptState, State handleState, 439 String stateFormClass) 440 throws NonHandleableException { 441 if (promptState == null || handleState == null) { 442 throw new NonHandleableException("Can't add null state in pairing."); 443 } 444 if (finalState != null) { 447 throw new NonHandleableException("Can't add states once final state has been added."); 448 } 449 if (promptStates.contains(promptState) || 450 promptStates.contains(handleState) || 451 handleStates.contains(promptState) || 452 handleStates.contains(handleState)) { 453 throw new NonHandleableException("Paired states must be unique."); 454 } 455 456 457 promptState.setStateFormClass(stateFormClass); 458 handleState.setStateFormClass(stateFormClass); 459 promptStates.add(promptState); 460 handleStates.add(handleState); 461 addState(promptState); 462 addState(handleState); 463 464 465 if (StringUtil.notNull(getInitialState()).equals("")) { 467 setInitialState(promptState.getName()); 468 } 469 470 471 Transition errorTransition = new Transition(); 474 errorTransition.setState(promptState.getName()); 475 errorTransition.setControllerObject(getClass().getName()); 476 handleState.setErrorTransition(errorTransition); 477 } 478 479 488 protected ActionForm findControllerForm(ControllerRequest request) 489 throws ControllerException { 490 ActionConfig config = ConfigManager.getActionConfig("", getClass().getName(), null); 491 if (config == null) { 494 return null; 495 } 496 497 String controllerFormAttribute = config.getAttribute(); 498 499 500 if (controllerFormAttribute == null) { return null; 502 } 503 504 505 PersistentSession session = request.getSession(); 507 508 509 if ("request".equals(config.getScope())) { 510 511 512 return (ActionForm) session.getAttribute(controllerFormAttribute); 514 } else { 515 return (ActionForm) session.getPersistentAttribute(controllerFormAttribute); 516 } 517 } 518 519 527 protected Transition getControllerChainingTransition() { 528 return controllerChainingTransition; 529 } 530 531 537 protected Transition getControllerSecurityTransition() { 538 return controllerSecurityTransition; 539 } 540 541 546 public State getFinalState() { 547 return finalState; 548 } 549 550 557 public String getInitialState() { 558 return (String ) initialStates.get(getClass().getName()); 559 } 560 561 562 567 protected final String getSchema() { 568 Stack mySchemaStack = (Stack ) schemas.get(getClass().getName()); 569 570 571 if (mySchemaStack == null) { 572 setSchema(ExpressoSchema.class.getName()); 573 mySchemaStack = (Stack ) schemas.get(getClass().getName()); 574 } 575 576 String returnValue = (String ) mySchemaStack.peek(); 577 return returnValue; 578 } 579 580 581 587 protected Schema getSchemaInstance() { 588 return SchemaFactory.getInstance().getSchema(this.getSchema()); 589 } 590 591 592 599 public synchronized Stack getSchemaHierarchy() { 600 return getSchemaStack(); 601 } 602 603 608 public synchronized Stack getSchemaStack() { 609 Stack s = (Stack ) schemas.get(getClass().getName()); 610 if (s == null) { 611 s = new Stack (); 612 schemas.put(this.getClass().getName(), s); 613 } 614 615 if (s.isEmpty()) { 616 s.push(com.jcorporate.expresso.core.ExpressoSchema.class.getName()); 617 } 618 619 return s; 620 } 621 622 628 public final State getState(String stateName) { 629 Hashtable myStateList = (Hashtable ) states.get(getClass().getName()); 630 631 632 if (myStateList == null) { 633 return null; 634 } 635 636 637 State stateClass = (State) myStateList.get(stateName); 638 639 640 if (stateClass == null) { 641 return null; 642 } 643 try { 644 State newStateClass = (State) stateClass.clone(); 645 newStateClass.setController(this); 646 647 648 return newStateClass; 649 } catch (CloneNotSupportedException cne) { 650 log.error("Unable to clone " + "State object '" + stateClass + 651 "'", cne); 652 } catch (ControllerException ce) { 653 log.error("Unable to clone " + "State object '" + stateClass + 654 "'", ce); 655 } 656 657 658 return null; 659 } 660 661 662 667 public final Hashtable getStates() { 668 Hashtable myStateList = (Hashtable ) states.get(getClass().getName()); 669 670 if (myStateList == null) { 671 return null; 672 } 673 674 return myStateList; 675 } 676 677 678 688 protected String getString(String stringCode) { 689 return this.getString(stringCode, new Object [0]); 690 } 691 692 693 704 protected String getString(String stringCode, Object [] args) { 705 String result = stringCode; 706 Stack s = (Stack ) schemas.get(this.getClass().getName()); 707 708 if (s == null || s.isEmpty()) { 709 result = Messages.getString(getSchema(), stringCode, args); 710 } else { 711 Locale theLocale = Messages.getDefaultLocale(); 712 result = Messages.getString(s, theLocale, stringCode, args); 713 } 714 715 return result; 716 } 717 718 719 724 public String getTitle() { 725 return ("No Title"); 726 } 727 728 729 744 protected void handleException(HttpServletRequest req, 745 ControllerRequest creq, String dbName, 746 String userName, Throwable theException) 747 throws ServletException { 748 if (StringUtil.notNull(dbName).equals("")) { 749 dbName = "default"; 750 } 751 752 if (creq == null || dbName == null || req == null || userName == null) { 753 log.error("Error handling exception", theException); 754 throw new ServletException ("ControllerRequest Error", theException); 755 } 756 757 try { 758 ControllerResponse errorResponse = new ControllerResponse(); 759 errorResponse.setRequest(creq); 760 errorResponse.setTitle(getTitle()); 761 errorResponse.setSchemaStack((java.util.Stack ) this.getSchemaStack().clone()); 762 errorResponse.setControllerClass(getClass().getName()); 763 764 765 766 boolean showStack = true; 767 768 769 try { 770 if (ConfigManager.getContext(dbName) != null) { 771 showStack = ConfigManager.getContext(dbName).showStackTrace(); 772 } 773 } catch (ConfigurationException ce) { 774 throw new ServletException (ce); 775 } 776 if (showStack) { 777 if (theException != null) { 778 ByteArrayOutputStream bos = new ByteArrayOutputStream (); 779 theException.printStackTrace(new PrintStream (bos)); 780 errorResponse.addOutput(new Output("stackTrace", 781 bos.toString())); 782 } else { 783 errorResponse.addOutput(new Output("stackTrace", 784 "No stack trace was available")); 785 } 786 } else { 787 errorResponse.addOutput(new Output("stackTrace", 788 "Stack trace display is not " + "enabled.")); 789 } 790 791 792 errorResponse.addOutput(new Output("exceptionMessage", 793 theException.getMessage())); 794 795 796 if (theException instanceof com.jcorporate.expresso.kernel.exception.ChainedException) { 797 com.jcorporate.expresso.kernel.exception.ChainedException c = (com.jcorporate.expresso.kernel.exception.ChainedException) theException; 798 Throwable nestedException = c.getNested(); 799 800 801 if (nestedException != null) { 802 String nested = StringUtil.notNull(c.getNested().getMessage()); 803 804 805 if (theException.getMessage().indexOf(nested) == -1) { 806 errorResponse.addOutput(new Output("nestedMessage", 807 nested)); 808 } 809 } 810 if (c.getErrorNumber() != 0) { 811 errorResponse.addOutput(new Output("errorNumber", 812 Integer.toString(c.getErrorNumber()))); 813 } 814 } 815 816 817 errorResponse.addOutput(new Output("requestedURL", 818 StringUtil.notNull(req.getRequestURI()))); 819 errorResponse.addOutput(new Output("queryString", 820 StringUtil.notNull(req.getQueryString()))); 821 errorResponse.addOutput(new Output("db", dbName)); 822 errorResponse.addOutput(new Output("userName", userName)); 823 errorResponse.addOutput(new Output("dbDescrip", 824 ConfigManager.getContext(dbName).getDescription())); 825 errorResponse.addOutput(new Output("errorClass", 826 theException.getClass().getName())); 827 828 829 if (theException instanceof SecurityException ) { 830 errorResponse.addOutput(new Output("errorType", "security")); 831 addRequestedURLtoSession(req, creq); 832 } else if (theException instanceof DBException) { 833 errorResponse.addOutput(new Output("errorType", "database")); 834 835 836 DBException de = (DBException) theException; 837 errorResponse.addOutput(new Output("dbMessage", 838 de.getDBMessage())); 839 } else { 840 errorResponse.addOutput(new Output("errorType", "other")); 841 } 842 843 844 errorResponse.addOutput(new Output("controllerClass", 845 getClass().getName())); 846 req.setAttribute(ExpressoConstants.CONTROLLER_RESPONSE_KEY, errorResponse); 847 848 849 850 boolean mailError = false; 851 852 853 try { 854 String servletEventFlag = StringUtil.notNull(Setup.getValue(dbName, "ServletEvent")); 855 856 857 if (StringUtil.toBoolean(servletEventFlag)) { 858 mailError = true; 859 } else if (servletEventFlag.equalsIgnoreCase("E")) { 860 if (!(theException instanceof SecurityException )) { 861 mailError = true; 862 } 863 } 864 } catch (Exception e) { 865 log.error("Unable to email error correctly", e); 866 } 867 if (!mailError) { 868 log.info("Sending of '" + theException.getClass().getName() + 869 "' errors via email is not enabled in " + 870 "db/context '" + dbName + "'"); 871 } else { 872 FastStringBuffer theMessage = FastStringBuffer.getInstance(); 873 try { 874 theMessage.append("Error:\n"); 875 theMessage.append("\tA " + 876 theException.getClass().getName() + 877 " Error occurred at " + 878 DateTime.getDateTimeForDB(dbName) + 879 " in database/context '" + dbName + 880 "' to user '" + userName + "'\n"); 881 theMessage.append("\tThe requested URL was '"); 882 theMessage.append(getRequestURL(req)); 883 theMessage.append("'\n"); 884 885 String errorMessage = theException.getMessage(); 886 887 if (errorMessage != null) { 888 theMessage.append("\t"); 889 theMessage.append(errorMessage); 890 } else { 891 theMessage.append("No error message was available"); 892 } 893 894 895 theMessage.append(errorResponse.getOutput("stackTrace").getContent()); 896 String finalMessage = theMessage.toString(); 897 log.error(finalMessage, theException); 898 EventHandler.Event(dbName, "SYSERROR", 899 finalMessage, false); 900 } catch (Exception ee) { 901 log.error("Unable to send error email", ee); 902 } finally { 903 theMessage.release(); 904 theMessage = null; 905 } 906 907 } 908 909 } catch (NullPointerException npe) { 910 log.error("Null Pointer Exception while handling error", npe); 911 throw new ServletException (npe); 912 } catch (ControllerException ce) { 913 log.error("ControllerException while handling error", ce); 914 throw new ServletException (ce); 915 } catch (Exception ee) { 916 log.error("Exception while handling error", ee); 917 throw new ServletException (ee); 918 } 919 } 920 921 922 925 protected void addRequestedURLtoSession(HttpServletRequest req, 926 ControllerRequest creq) 927 throws ControllerException { 928 PersistentSession session = creq.getSession(); 929 930 if (session != null) { 931 String origUrl = getRequestURL(req); 932 session.setPersistentAttribute(ExpressoConstants.CONTROLLER_ORIGINAL_URL_KEY, 933 new SerializableString(origUrl)); 934 } 935 } 936 937 940 protected String getRequestURL(HttpServletRequest req) { 941 String origUrl = StringUtil.notNull(req.getRequestURI()); 942 943 if (req.getQueryString() != null) { 944 origUrl = origUrl + "?" + req.getQueryString(); 945 } 946 return origUrl; 947 } 948 949 956 protected void addRegDomainParamtoSession(HttpServletRequest req, 957 ControllerRequest creq, 958 String regDomain) 959 throws ControllerException { 960 PersistentSession session = creq.getSession(); 961 962 if (session != null) { 963 session.setPersistentAttribute("regDomain", 964 new SerializableString(regDomain)); 965 } 966 } 967 968 977 public static synchronized Controller instantiate(String className) 978 throws ControllerException { 979 StringUtil.assertNotBlank(className, 980 "Controller class name " + 981 " may not be blank or null here"); 982 983 984 try { 985 986 Class c = ClassLocator.loadClass(className); 987 return (Controller) c.newInstance(); 988 } catch (ClassNotFoundException cn) { 989 throw new ControllerException("Controller object '" + className + 990 "' not found", cn); 991 } catch (InstantiationException ie) { 992 throw new ControllerException("Controller object '" + className + 993 "' cannot be instantiated", ie); 994 } catch (IllegalArgumentException e) { 995 throw new ControllerException("Controller object '" + className + 996 "' cannot be instantiated (IllegalArgumentException", 997 e); 998 } catch (IllegalAccessException iae) { 999 throw new ControllerException("llegal access loading " + 1000 "Controller object '" + className + 1001 "'", iae); 1002 } 1003 } 1004 1005 1006 1013 protected boolean isFinalState(String newState) { 1014 if (finalState == null) { 1015 return false; 1016 } 1017 1018 return finalState.getName().equals(newState); 1019 } 1020 1021 1028 protected boolean isHandleState(State nextState) { 1029 return handleStates.contains(nextState); 1030 } 1031 1032 1039 protected boolean isPromptState(State nextState) { 1040 return promptStates.contains(nextState); 1041 } 1042 1043 1053 protected StateForm loadStateForm(State nextState, 1054 ActionForm controllerForm) 1055 throws ControllerException { 1056 StateForm stateForm = null; 1057 String stateFormClass = StringUtil.notNull(nextState.getStateFormClass()); 1058 1059 1060 if (controllerForm == null) { 1061 if (!stateFormClass.equals("")) { 1062 throw new ControllerException("Controller needs ActionForm because it's state expects one."); 1063 } 1064 1065 1066 return (null); 1067 } else { 1068 1069 1070 if (stateFormClass.equals("")) { 1072 1073 if (controllerForm instanceof DefaultForm) { 1074 return (StateForm) controllerForm; 1075 } else { 1076 return (null); } 1078 } else { 1079 1080 1081 try { 1083 1084 Class clazz = ClassLocator.loadClass(nextState.getStateFormClass()); 1085 stateForm = (StateForm) clazz.newInstance(); 1086 1087 1088 try { 1089 BeanUtils.populate(stateForm, 1090 BeanUtils.describe(controllerForm)); 1091 } catch (Exception e) { 1092 throw new ControllerException(e); 1093 } 1094 } catch (Throwable t) { 1095 throw new ControllerException(t); 1096 } 1097 1098 1099 return (stateForm); 1100 } 1101 } 1102 } 1103 1104 1122 public ControllerResponse newState(String newState, 1123 ControllerRequest myRequest) 1124 throws ControllerException, 1125 NonHandleableException { 1126 newState = StringUtil.notNull(newState); 1127 1128 if (log.isDebugEnabled()) { 1129 log.debug("Transitioning to state '" + newState + 1130 "' in controller '" + getClass().getName() + "'"); 1131 } 1132 if (newState.length() == 0) { 1133 if (getInitialState() != null) { 1134 return newState(getInitialState(), myRequest); 1135 } else { 1136 throw new ControllerException("You must specify a " + 1137 "non-blank state. No default initial state is specified."); 1138 } 1139 } 1140 1141 1142 String entryState = newState; 1145 1146 1147 1148 State nextState = getState(newState); 1149 1150 1151 if (nextState == null) { 1152 throw new ControllerException("State '" + newState + 1153 "' is unknown for Controller " + 1154 getClass().getName()); 1155 } 1156 1157 1158 1159 if (!newState.equals("")) { 1161 if (controllerSecurityTransition == null && !stateAllowed(newState, myRequest)) { 1162 DelayThread.delay(); 1163 throw new SecurityException ("State '" + 1164 nextState.getDescription() + 1165 "' is not allowed for user '" + 1166 myRequest.getUser() + "' (" + 1167 myRequest.getUid() + ")" + 1168 " in controller '" + getTitle() + 1169 "' (" + getClass().getName() + 1170 ") in context '" + 1171 myRequest.getDataContext() + "'"); 1172 } 1173 1174 1175 } 1176 1177 1178 setupReturnToSender(nextState, myRequest); 1179 1180 1182 PersistentSession mySession = myRequest.getSession(); 1183 mySession.removePersistentAttribute("previousState"); 1184 mySession.setPersistentAttribute("previousState", newState); 1185 mySession.removePersistentAttribute("previousController"); 1186 mySession.setPersistentAttribute("previousController", this.getClass().getName()); 1187 1188 1189 1190 if (isFinalState(newState)) { 1199 FastStringBuffer fsb = FastStringBuffer.getInstance(); 1201 String returnToSender = null; 1202 try { 1203 Transition t = nextState.getReturnToSender(); 1204 returnToSender = t.toXML(fsb).toString(); 1205 } finally { 1206 fsb.release(); 1207 fsb = null; 1208 } 1209 1210 1211 for (Iterator i = handleStates.iterator(); i.hasNext();) { 1212 State oneHandleState = (State) i.next(); 1213 1214 1215 myRequest.setParameter(RETURN_TO_SENDER_TRAN, returnToSender); 1217 1218 1219 ControllerResponse statusResponse = newState(oneHandleState.getName(), 1220 myRequest); 1221 1222 1223 if (!statusResponse.getCurrentState().getName().equals(oneHandleState.getName())) { 1224 return statusResponse; } 1226 } 1228 1229 } 1230 1231 ServletControllerResponse myResponse = new ServletControllerResponse(); 1234 1235 if (myRequest == null) { 1236 throw new NonHandleableException("Request cannot be null here"); 1237 } 1238 1239 1240 myResponse.setRequest(myRequest); 1241 myResponse.setTitle(getTitle()); 1242 myResponse.setCurrentState(nextState); 1243 myResponse.setSchemaStack((java.util.Stack ) this.getSchemaStack().clone()); 1244 myResponse.setControllerClass(getClass().getName()); 1245 1246 1247 1248 String oneParamName = null; 1249 String oneParamValue = null; 1250 1251 1252 for (Enumeration pe = nextState.getParameters().elements(); 1253 pe.hasMoreElements();) { 1254 oneParamName = (String ) pe.nextElement(); 1255 oneParamValue = StringUtil.notNull(myRequest.getParameter(oneParamName)).trim(); 1256 1257 1258 if (oneParamValue.equals("")) { 1259 throw new ControllerException("Value for parameter '" + 1260 oneParamName + 1261 "' is required for state " + 1262 nextState.getDescription() + 1263 " (" + nextState.getName() + 1264 ")"); 1265 } 1266 1267 1268 } 1269 1270 1271 processRequestTransitions(nextState, myRequest); 1272 1273 1274 1275 1276 1277 ActionForm controllerForm = findControllerForm(myRequest); 1279 StateForm stateForm = loadStateForm(nextState, controllerForm); 1280 1282 1283 ControllerResponse cr = null; 1284 1285 1286 if (!newState.equals(entryState)) { 1288 throw new ControllerException("newState was modified between method entry and security check!"); 1289 } 1290 1291 1292 if (controllerSecurityTransition != null && !stateAllowed(newState, myRequest)) { 1293 Transition securityTransition = null; 1295 1296 1297 try { 1298 securityTransition = (Transition) controllerSecurityTransition.clone(); 1299 } catch (CloneNotSupportedException cne) { 1300 throw new ControllerException("Cannot clone the securityTransition class"); 1301 } 1302 1303 nextState.setSuccessTransition(securityTransition); 1306 cr = myResponse; 1307 } else { 1308 prePerform(nextState, myRequest, myResponse); 1310 nextState.perform(stateForm, myRequest, myResponse); 1311 1312 cr = nextState.getResponse(); 1313 } 1314 1315 unloadStateForm(stateForm, controllerForm); 1317 1318 1319 if (processTransitions(myRequest, cr, nextState) != null) { 1320 return cr; 1321 } 1322 1323 1324 addPromptTransitions(nextState, cr); 1325 1326 1327 if (nextState.getClass().getName() 1330 .equals("com.jcorporate.expresso.core.controller.State")) { 1331 Class thisClass = this.getClass(); 1332 Class tryClass = thisClass; 1334 1335 try { 1336 1337 1338 boolean methodFound = false; 1339 Method m = null; 1340 1341 1342 while (!methodFound) { 1348 try { 1349 m = tryClass.getDeclaredMethod(nextState.getHandlerName(), stateHandlerParams); 1350 methodFound = true; 1351 } catch (NoSuchMethodException nsme) { 1352 if (myRequest instanceof ServletControllerRequest) { 1353 try { 1356 m = tryClass.getDeclaredMethod(nextState.getHandlerName(), 1357 servletStateHandlerParams); 1358 methodFound = true; 1359 } catch (NoSuchMethodException ex) { 1360 if (log.isDebugEnabled()) { 1361 log.debug("Didn't find ServletControllerRequest method"); 1362 } 1363 } 1364 } 1365 1366 if (!methodFound) { 1367 tryClass = tryClass.getSuperclass(); 1368 1369 if (tryClass == null) { 1370 throw nsme; 1371 } 1372 } 1373 } 1374 } 1375 if (m == null) { 1376 throw new NonHandleableException("Null pointer when we should have a method object"); 1377 } 1378 1379 1380 Object [] invokeParams = {myRequest, cr}; 1381 m.setAccessible(true); 1382 1383 1384 ControllerResponse cr2 = (ControllerResponse) m.invoke(this, 1385 invokeParams); 1386 1387 1388 if (cr2 != null) { 1389 ErrorCollection eold = cr.getErrors(); 1390 cr = cr2; 1391 cr.saveErrors(eold); 1392 } 1393 1394 postPerform(nextState, myRequest, myResponse); 1395 } catch (SecurityException se) { 1396 log.error("Unable to reflect to method: " + 1397 this.getClass().getName() + "." + 1398 nextState.getHandlerName() + 1399 " setAccessible permissions need to be allowed from your security policy", 1400 se); 1401 throw new NonHandleableException(se); 1402 } catch (IllegalAccessException illae) { 1403 log.error("Unable to reflect to method: " + 1404 this.getClass().getName() + "." + 1405 nextState.getHandlerName() + 1406 "illegal access Exception", illae); 1407 throw new NonHandleableException(illae); 1408 } catch (IllegalArgumentException iae) { 1409 log.error("Illegal Argument Exception", iae); 1410 throw new NonHandleableException(iae); 1411 } catch (InvocationTargetException ite) { 1412 Throwable e = ite.getTargetException(); 1413 log.error("Error in substate", e); 1414 e.printStackTrace(); 1415 1416 if (e instanceof NonHandleableException) { 1417 throw new NonHandleableException(e); } else if (e instanceof SecurityException ) { 1419 throw new SecurityException (e.getMessage()); 1420 } else { 1421 throw new ControllerException(e); 1422 } 1423 } catch (NoSuchMethodException nsme) { 1424 try { 1425 1426 thisClass.getDeclaredMethod("newState", 1428 newStateParams); 1429 1430 if (log.isDebugEnabled()) { 1432 log.debug("Method '" + nextState.getHandlerName() + 1433 "' does not exist in controller class '" + 1434 getClass().getName() + 1435 "'. State must be handled by newState method."); 1436 } 1437 } catch (NoSuchMethodException nsme2) { 1438 1439 1440 String errMsg = ("Method '" + 1443 nextState.getHandlerName() + 1444 "' does not exist in '" + 1445 getClass().getName() + 1446 "' and there is no 'newState' method to handle " + 1447 "transitions. Unable to transition"); 1448 log.error(errMsg, nsme); 1449 throw new ControllerException(errMsg, nsme); 1450 } 1451 } 1452 } 1453 1454 ErrorCollection finalErrors = cr.getErrors(); 1456 if (finalErrors != null) { 1457 if (finalErrors.getErrorCount() > 0) { 1458 String errorState = nextState.getErrorState(); 1459 if (errorState != null) { 1460 cr.setFormCache(); transition(errorState, myRequest, cr); 1462 return cr; 1463 } 1464 } 1465 } 1466 1467 return cr; 1468 } 1469 1470 1471 1483 protected void prePerform(State nextState, 1484 ControllerRequest request, 1485 ControllerResponse response) throws ControllerException { 1486 } 1487 1488 1489 1502 protected void postPerform(State nextState, 1503 ControllerRequest request, 1504 ControllerResponse response) throws ControllerException { 1505 } 1506 1507 1515 protected String nextHandleState(State nextState) { 1516 String nextHandle = null; 1517 int i = promptStates.indexOf(nextState); 1518 1519 1520 if (i != -1) { State handleState = (State) handleStates.get(i); 1522 nextHandle = handleState.getName(); 1523 } 1524 1525 1526 return nextHandle; 1527 } 1528 1529 1538 protected String nextPromptState(State nextState) { 1539 String nextPrompt = null; 1540 int i = promptStates.indexOf(nextState); 1541 i++; 1542 1543 1544 if ((i > 0) && (i < promptStates.size())) { State promptState = (State) promptStates.get(i); 1546 nextPrompt = promptState.getName(); 1547 } 1548 1549 1550 return nextPrompt; 1551 } 1552 1553 1559 protected void endTimer(long beginTimer, HttpServletRequest request) { 1560 if (log.isInfoEnabled()) { 1561 log.info("Request '" + getRequestURL(request) + 1562 "', total time " + 1563 (System.currentTimeMillis() - beginTimer) + 1564 " milliseconds"); 1565 } 1566 } 1567 1568 1584 public ActionForward execute(ActionMapping mapping, ActionForm form, 1585 HttpServletRequest request, HttpServletResponse response) 1586 throws IOException , ServletException { 1587 long beginTimer = System.currentTimeMillis(); 1588 1589 1590 ErrorCollection actionErrors = new ErrorCollection(); 1591 1592 ControllerRequest queuedRequest = (ControllerRequest) request.getAttribute( 1594 ExpressoConstants.CONTROLLER_REQUEST_KEY); 1595 1596 if (queuedRequest != null) { 1598 request.removeAttribute(ExpressoConstants.CONTROLLER_REQUEST_KEY); 1599 String queuedState = StringUtil.notNull(request.getParameter(STATE_PARAM_KEY)); 1600 1601 if (queuedState.equals("")) { 1606 if (form instanceof ControllerForm) { 1608 ((ControllerForm) form).resetController(); 1609 } 1610 } 1611 1612 1614 1619 1620 ControllerResponse queuedResponse = null; 1621 1622 try { 1623 queuedRequest.setFormAttribute(mapping.getAttribute()); 1624 1626 1629 if (mapping.getValidate()) { 1630 actionErrors = (ErrorCollection) form.validate(mapping, request); 1631 } 1632 1633 if (actionErrors.size() == 0) { 1634 1635 queuedResponse = newState(queuedState, queuedRequest); 1636 } else { 1637 1638 1639 String previousController = request.getSession().getAttribute("previousController").toString(); 1640 String previousState = request.getSession().getAttribute("previousState").toString(); 1641 1642 if (previousController.equals(this.getClass().getName())) { 1643 queuedResponse = newState(StringUtil.notNull(previousState), 1644 queuedRequest); 1645 queuedResponse.saveErrors(actionErrors); 1646 } else { 1647 1648 transition(StringUtil.notNull(previousState),Class.forName(StringUtil.notNull(previousController)),queuedRequest, new ControllerResponse()); 1649 } 1650 1651 } 1652 } catch (Exception e) { 1653 request.setAttribute(ExpressoConstants.NEWSTATE_EXCEPTION_KEY, e); 1654 return (null); 1656 } 1657 1658 request.setAttribute(ExpressoConstants.CONTROLLER_REQUEST_KEY, queuedRequest); 1659 request.setAttribute(ExpressoConstants.CONTROLLER_RESPONSE_KEY, queuedResponse); 1660 1661 return (null); 1662 } 1663 1664 1665 1666 String dbName = null; 1667 String userName = null; 1668 ServletControllerRequest req = null; 1669 1670 1671 try { 1672 String requestDB = request.getParameter("db"); 1673 log.debug("request.getParameter(\"db\") = `" + request.getParameter("db") + "'"); 1675 CheckLogin.getInstance().checkLogin(request, requestDB); 1676 1677 1678 boolean multiPart = false; 1679 1680 if (form != null) { 1681 MultipartRequestHandler mp = form.getMultipartRequestHandler(); 1688 1689 if (mp != null) { 1690 if (log.isDebugEnabled()) { 1695 log.debug("Multipart request"); 1696 } 1697 1698 multiPart = true; 1699 req = ServletControllerRequest.parseParamsMultiPart(mp, mapping, form, 1700 request, response, this); 1701 req.setCallingServlet(this.getServlet()); 1703 } 1704 } 1705 if (!multiPart) { 1706 if (log.isDebugEnabled()) { 1709 log.debug("Non-multipart request"); 1710 } 1711 req = ServletControllerRequest.parseParams(mapping, form, request, response, this); 1712 req.setCallingServlet(this.getServlet()); 1714 } 1715 1716 1717 ErrorCollection errors = (ErrorCollection) req.getSession().getAttribute(Globals.ERROR_KEY); 1728 if (errors == null) { 1729 errors = (ErrorCollection) req.getSession().getPersistentAttribute(Globals.ERROR_KEY); 1731 if (errors != null) { 1733 req.getSession().removePersistentAttribute(Globals.ERROR_KEY); 1734 req.getSession().setAttribute(Globals.ERROR_KEY, errors); 1735 } 1736 } 1737 1738 1739 1749 String controllerRequested = StringUtil.notNull(req.getParameter(ExpressoConstants.CONTROLLER_KEY)); 1750 1751 String requestedState = StringUtil.notNull(req.getParameter(STATE_PARAM_KEY)); 1760 1761 log.debug("requestedState = `" + requestedState + "'"); 1762 if (!controllerRequested.equals("")) { 1763 if (!controllerRequested.equals(getClass().getName())) { 1764 1765 ActionConfig mm = ConfigManager.getActionConfig("", controllerRequested, requestedState); 1769 if (mm == null) { 1770 throw new ServletException ("The controller requested: " 1771 + controllerRequested.toString() 1772 + " and/or state within that controller: " 1773 + requestedState.toString() 1774 + " are not available in configuration mapping; if you expected this to be " 1775 + "available, double-check the /config/*-config.xml files."); 1776 } 1777 1778 FastStringBuffer newURL = FastStringBuffer.getInstance(); 1782 String urlString = null; 1783 try { 1784 newURL.append(mm.getPath()); 1785 newURL.append(".do"); 1786 newURL.append("?state="); 1787 newURL.append(requestedState); 1788 1789 1790 String oneParamName = null; 1791 String oneParamValue = null; 1792 1793 for (Enumeration ep = req.getParameters().keys(); 1796 ep.hasMoreElements();) { 1797 oneParamName = (String ) ep.nextElement(); 1798 oneParamValue = req.getParameter(oneParamName); 1799 newURL.append("&"); 1800 newURL.append(oneParamName); 1801 newURL.append("="); 1802 newURL.append(oneParamValue); 1803 } 1804 1805 if (log.isDebugEnabled()) { 1806 log.debug("Request to controller '" + 1807 getClass().getName() + 1808 "' was for a transition " + "to class '" + 1809 controllerRequested + 1810 "', so forwarding to URL '" + 1811 newURL.toString() + "'"); 1812 } 1813 if (log.isInfoEnabled()) { 1814 endTimer(beginTimer, request); 1815 } 1816 1817 } finally { 1818 urlString = newURL.toString(); 1819 newURL.release(); 1820 newURL = null; 1821 } 1822 1823 GenericDispatcher.forward(request, response, urlString); 1825 request.removeAttribute(ExpressoConstants.USED_ROUTING_KEY); 1826 return null; 1827 } 1828 } 1829 1830 1831 request.setAttribute(ExpressoConstants.USED_ROUTING_KEY, "inuse"); 1837 1838 if (ConfigManager.getContext(req.getDataContext()).isUseSSL()) { 1843 1844 1845 if (log.isDebugEnabled()) { 1846 log.debug("Checking if we need to redirect to different protocol"); 1847 } 1848 Hashtable myStateList = (Hashtable ) states.get(getClass().getName()); 1849 String stateName = req.getParameter(STATE_PARAM_KEY); 1850 if (stateName == null || stateName.length() == 0) { 1851 stateName = this.getInitialState(); 1852 } 1853 1854 1855 if (this.checkSsl(request, response, 1856 ((State) myStateList.get(stateName)).isSecure())) { 1857 return null; 1858 } 1859 1860 1861 if (log.isDebugEnabled()) { 1862 log.debug("No more redirection necessary"); 1863 } 1864 } 1865 1866 if (log.isDebugEnabled()) { 1867 log.debug("Controller '" + getClass().getName() + 1868 "' to state '" + 1869 StringUtil.notNull(req.getParameter(STATE_PARAM_KEY)) + "'"); 1870 } 1871 1872 req.setFormAttribute(mapping.getAttribute()); 1873 1874 if (requestedState.equals("")) { 1881 if (form instanceof ControllerForm) { 1883 ((ControllerForm) form).resetController(); 1884 } 1885 } 1886 1887 1909 1910 1911 if (form instanceof DefaultForm) { 1912 try { 1913 ((DefaultForm) form).setUsingHashtableParameters(req.getParameters()); 1914 } catch (Exception ex) { 1915 ex.printStackTrace(); 1916 throw new ServletException (ex); 1917 } 1918 } 1919 1920 1929 1930 1931 request.removeAttribute(ExpressoConstants.CONTROLLER_RESPONSE_KEY); 1934 dbName = req.getDataContext(); 1935 userName = req.getUser(); 1936 if (log.isDebugEnabled()) { 1937 log.debug("Before newstate in '" + getClass().getName() + "'"); 1938 } 1939 1940 ControllerResponse res = null; 1946 try { 1947 1952 1953 if (mapping.getValidate()) { 1954 actionErrors = (ErrorCollection) form.validate(mapping, request); 1955 } 1956 1957 if (actionErrors.size() == 0) { 1958 1959 res = newState(StringUtil.notNull(requestedState), req); 1960 } else { 1961 1962 1963 String previousController = request.getSession().getAttribute("previousController").toString(); 1964 String previousState = request.getSession().getAttribute("previousState").toString(); 1965 1966 if (previousController.equals(this.getClass().getName())) { 1967 res = newState(StringUtil.notNull(previousState), req); 1968 res.saveErrors(actionErrors); 1969 } else { 1970 1971 transition(StringUtil.notNull(previousState),Class.forName(StringUtil.notNull(previousController)),req, new ControllerResponse()); 1972 } 1973 } 1974 1975 } finally { 1976 if (form != null && "session".equals(mapping.getScope())) { 1977 form.setMultipartRequestHandler( null); 1983 } 1984 } 1985 1986 if (log.isDebugEnabled()) { 1987 log.debug("After newstate in '" + getClass().getName() + 1988 "' controller is '" + res.getControllerClass() + "'"); 1989 } 1990 1991 res.setRequestPath(mapping.getPath()); 1993 request.setAttribute(ExpressoConstants.CONTROLLER_RESPONSE_KEY, res); 1994 1995 if (res.isCustomResponse()) { 2000 if (log.isInfoEnabled()) { 2004 endTimer(beginTimer, request); 2005 } 2006 request.removeAttribute(ExpressoConstants.USED_ROUTING_KEY); 2007 return null; 2008 } 2009 2010 ActionConfig finalConfig = mapping; 2011 2012 if (!res.getControllerClass().equals(mapping.getType())) { 2016 if (log.isDebugEnabled()) { 2017 log.debug("Controller '" + getClass().getName() + 2018 "' transitioned internally to controller '" + 2019 res.getControllerClass() + "', state '" + 2020 res.getCurrentState() + 2021 "'. Getting alternate mapping..."); 2022 } 2023 2024 2027 ActionConfig config = ConfigManager.getActionConfig("", res.getControllerClass(), 2028 res.getCurrentState().getName()); 2029 2030 if (config == null) { 2031 throw new ControllerException("Unable to find ActionConfig for: " 2032 + res.getControllerClass() + ":" + res.getCurrentState().getName()); 2033 } 2034 finalConfig = config; 2035 2036 if (log.isDebugEnabled()) { 2037 log.debug("Got mapping for '" + finalConfig.getPath() + "'"); 2038 } 2039 } else { 2040 if (log.isDebugEnabled()) { 2041 log.debug("Controller '" + getClass().getName() + 2042 "' using type '" + finalConfig.getType() + 2043 "', transitioning to state '" + 2044 res.getCurrentState() + 2045 "' within the same controller."); 2046 } 2047 } 2048 2049 ActionForward fwd = getActionForward(req, finalConfig, res); 2052 2053 if (log.isInfoEnabled()) { 2054 endTimer(beginTimer, request); 2055 } 2056 2057 request.removeAttribute(ExpressoConstants.USED_ROUTING_KEY); 2059 return fwd; 2061 } catch (NonHandleableException ne) { 2062 throw new ServletException (ne); 2063 2066 } catch (SecurityException securExcep) { 2067 if (userName.equals(User.UNKNOWN_USER)) { 2069 ActionForward loginForward = mapping.findForward(ExpressoConstants.APPLICATION_LOGON_FORWARD); 2072 if (loginForward == null) { 2073 try { 2075 throw new Exception ( 2076 "cannot find forward for 'logon'; one should be in <application>-config.xml"); 2077 } catch (Exception e) { 2078 e.printStackTrace(System.err); 2079 handleException(request, req, dbName, userName, e); 2080 return (mapping.findForward(ExpressoConstants.ERROR_FORWARD)); 2081 } 2082 } 2083 2084 try { 2085 addRequestedURLtoSession(request, req); 2086 } catch (Exception e) { 2087 log.error("unexpected problem adding item to session: ", e); 2090 } 2091 2092 redirectRequest(response, ConfigManager.getContextPath() + loginForward.getPath()); 2096 return null; 2097 } else { 2098 2101 try { 2103 ControllerSecurity cs = new ControllerSecurity(); 2104 RegistrationDomain rd = new RegistrationDomain(); 2105 ControllerSecurity oneSecurityEntry = null; 2106 String groupName = null; 2107 cs.setDataContext(dbName); 2108 2109 cs.setField("ControllerClass", getClass().getName()); 2112 for (Iterator cse = cs.searchAndRetrieveList().iterator(); cse.hasNext();) { 2113 cs.clear(); 2114 oneSecurityEntry = (ControllerSecurity) cse.next(); 2115 groupName = oneSecurityEntry.getField("GroupName"); 2116 rd.clear(); 2118 rd.setField("GroupName", groupName); 2119 if (rd.find()) { 2120 ActionForward registrationForward = mapping.findForward(ExpressoConstants.REGISTER_FORWARD); 2122 2123 if (registrationForward == null) { 2124 try { 2126 throw new Exception ( 2127 "cannot find forward for '" + ExpressoConstants.REGISTER_FORWARD + "'; One should be defined in <application>-config.xml"); 2128 } catch (Exception e) { 2129 e.printStackTrace(System.err); 2130 handleException(request, req, dbName, userName, e); 2131 2132 return (mapping.findForward(ExpressoConstants.ERROR_FORWARD)); 2133 } 2134 } 2135 2136 try { 2137 addRegDomainParamtoSession(request, req, rd.getField("Name")); 2138 2139 } catch (Exception e) { 2140 log.error("unexpected problem adding item to session: ", e); 2143 } 2144 2145 2146 try { 2150 ErrorCollection ec = req.getErrorCollection(); 2151 if (ec == null) { 2152 ec = new ErrorCollection(); 2153 } 2154 ec.addError(securExcep.getMessage()); 2155 req.getSession().setPersistentAttribute(Globals.ERROR_KEY, ec); 2156 } catch (ControllerException ex) { 2157 log.error("Unable to save error for a permission denied message", ex); 2158 } 2159 redirectRequest(response, ConfigManager.getContextPath() + registrationForward.getPath()); 2160 return null; 2161 2162 } else { 2163 log.warn( 2164 "Registration Domain for " + groupName + " and class " + getClass().getName() + " not found"); 2165 } 2166 } 2167 } catch (DBException dbe) { 2168 handleException(request, req, dbName, userName, dbe); 2169 } 2170 2171 System.err.println(securExcep.getMessage()); 2174 handleException(request, req, dbName, userName, securExcep); 2175 2176 return (mapping.findForward(ExpressoConstants.ERROR_FORWARD)); 2177 } 2178 } catch (NullPointerException npe) { 2179 npe.printStackTrace(System.err); 2180 log.error("Null Pointer Exception", npe); 2181 handleException(request, req, dbName, userName, npe); 2182 return (mapping.findForward("error")); 2183 } catch (Exception ee) { 2184 ee.printStackTrace(System.err); 2185 handleException(request, req, dbName, userName, ee); 2186 return (mapping.findForward("error")); 2187 } 2188 } 2189 2190 2203 protected ActionForward getActionForward(ServletControllerRequest req, 2204 ActionConfig mapping, 2205 ControllerResponse res) throws NonHandleableException, 2206 ControllerException { 2207 2208 ForwardConfig fwd = null; 2209 2210 2211 if (!StringUtil.notNull(req.getParameter("style")).equals("")) { 2212 String style = req.getParameter("style"); 2213 fwd = mapping.findForwardConfig(style); 2214 2215 2216 if (fwd == null) { 2217 fwd = mapping.getModuleConfig().findForwardConfig(style); 2218 if (fwd == null) { 2219 throw new NonHandleableException("Style '" + 2220 req.getParameter("style") + 2221 "' was not found for controller '" + 2222 res.getControllerClass() + 2223 "'"); 2224 } 2225 } 2226 } else if (res instanceof ServletControllerResponse) { 2227 2230 ServletControllerResponse resServ = (ServletControllerResponse) res; 2231 if (resServ.getActionForward() != null) { 2232 fwd = resServ.getActionForward(); 2233 } 2234 } 2235 2236 2239 if ((fwd == null) && (res.getStyle() != null)) { 2240 fwd = mapping.findForwardConfig(res.getStyle()); 2241 if (fwd == null) { 2242 fwd = mapping.getModuleConfig().findForwardConfig(res.getStyle()); 2243 } 2244 } 2245 2246 2249 if (fwd == null) { 2250 fwd = ConfigManager.findForwardConfig(mapping, res.getCurrentState().getName()); 2251 2252 } 2257 2259 if (fwd == null) { 2260 if (log.isDebugEnabled()) { 2261 log.debug("No forward for '" + 2262 res.getCurrentState().getName() + 2263 "' in controller '" + res.getControllerClass() + 2264 "' using mapping for '" + mapping.getPath() + 2265 "', which is for class '" + mapping.getType() + 2266 "'. Using default view."); 2267 } 2268 2269 2270 fwd = mapping.getModuleConfig().findForwardConfig("default"); 2271 } 2272 2273 fwd = remapFromExtension(fwd, mapping, req); 2274 2275 if (log.isDebugEnabled()) { 2276 if (fwd == null) { 2277 log.debug("Controller returning a null fwd object"); 2278 } else { 2279 log.debug("Controller '" + res.getControllerClass() + 2280 "', state '" + res.getCurrentState().getName() + 2281 "' forwarding to view '" + fwd.getPath() + "'"); 2282 } 2283 } 2284 2285 ActionForward forward = new ActionForward(fwd.getPath(), fwd.getPath() 2286 , fwd.getRedirect(), fwd.getContextRelative()); 2287 2288 return forward; 2289 } 2290 2291 2302 protected ForwardConfig remapFromExtension(ForwardConfig fwd, 2303 ActionConfig mapping, 2304 ServletControllerRequest req) throws ControllerException { 2305 2306 if (fwd != null) { 2307 String path = fwd.getPath(); 2308 if (path != null) { 2309 int lastDot = path.lastIndexOf('.'); 2310 if (lastDot != -1) { 2311 String ext = path.substring(lastDot); 2312 if (ext.equalsIgnoreCase(".xsl") || ext.equalsIgnoreCase(".xslt")) { 2313 fwd = mapping.getModuleConfig().findForwardConfig("xml"); 2314 if (fwd == null) { 2315 log.warn("cannot find action forward 'xml' which must be defined when using XSL forwards"); 2316 } 2317 req.setParameter("xsl", path); 2318 } 2319 } 2320 } 2321 } 2322 return fwd; 2323 } 2324 2325 2326 2333 protected void redirectRequest(HttpServletResponse response, 2334 String redirectURL) 2335 throws IOException { 2336 2337 2338 try { 2339 if (log.isDebugEnabled()) { 2340 log.debug("redirecting to: " + redirectURL); 2341 } 2342 2343 2344 response.sendRedirect(redirectURL); 2345 } catch (java.lang.IllegalStateException e) { 2346 log.error("Error performing redirect.", e); 2347 } 2348 2349 2350 } 2353 2354 2361 protected void populateStateForm(StateForm stateForm, 2362 ControllerRequest request) 2363 throws ControllerException { 2364 try { 2365 BeanUtils.populate(stateForm, request.getParameters()); 2366 } catch (Exception e) { 2367 throw new ControllerException(e); 2368 } 2369 } 2370 2371 2380 protected String previousPromptState(State nextState) { 2381 String previousPrompt = null; 2382 int i = promptStates.indexOf(nextState); 2383 2384 2385 if (i > 0) { State previousState = (State) promptStates.get(i - 1); 2387 previousPrompt = previousState.getName(); 2388 } 2389 2390 2391 return previousPrompt; 2392 } 2393 2394 2430 protected void processRequestTransitions(State nextState, 2431 ControllerRequest request) 2432 throws ControllerException { 2433 PersistentSession session = request.getSession(); 2434 String sessionKey = CTL_SUCC_TRAN + getClass().getName(); 2435 2436 2437 String controllerSuccessReturn = request.getParameter(CTL_SUCC_TRAN); 2439 2440 2441 if (controllerSuccessReturn != null) { 2442 request.removeParameter(CTL_SUCC_TRAN); 2443 session.setPersistentAttribute(sessionKey, controllerSuccessReturn); 2444 } else { 2445 String controllerSuccessReturnController = request.getParameter(CTL_SUCC_CTL); 2446 2447 2448 if (controllerSuccessReturnController != null) { 2449 String controllerSuccessReturnState = request.getParameter(CTL_SUCC_STATE); 2450 Transition t = new Transition(); 2451 t.setState(controllerSuccessReturnState); 2452 t.setControllerObject(controllerSuccessReturnController); 2453 FastStringBuffer fsb = FastStringBuffer.getInstance(); 2454 try { 2455 controllerSuccessReturn = t.toXML(fsb).toString(); 2456 } finally { 2457 fsb.release(); 2458 fsb = null; 2459 } 2460 session.setPersistentAttribute(sessionKey, 2461 controllerSuccessReturn); 2462 request.removeParameter(CTL_SUCC_CTL); 2463 request.removeParameter(CTL_SUCC_STATE); 2464 } 2465 } 2466 2467 2468 Transition successTransition = null; 2470 String successTran = request.getParameter(STATE_SUCC_TRAN); 2471 2472 2473 if (successTran != null) { 2474 request.removeParameter(STATE_SUCC_TRAN); 2475 2476 2477 try { 2478 successTransition = Transition.fromXML(successTran); 2479 } catch (Exception e) { 2480 throw new ControllerException(e); 2481 } 2482 } 2483 2484 2485 String stateSuccessReturnController = request.getParameter(STATE_SUCC_CTL); 2486 2487 2488 if (stateSuccessReturnController != null) { 2489 if (successTransition != null) { 2490 throw new ControllerException("State cannot handle stateSuccessReturn Transition object " + 2491 "AND stateSuccessXXX parameters in the same call."); 2492 } 2493 2494 2495 String stateSuccessReturnState = request.getParameter(STATE_SUCC_STATE); 2496 successTransition = new Transition(); 2497 successTransition.setState(stateSuccessReturnState); 2498 successTransition.setControllerObject(stateSuccessReturnController); 2499 request.removeParameter(STATE_SUCC_CTL); 2500 request.removeParameter(STATE_SUCC_STATE); 2501 } 2502 if (successTransition != null) { 2504 nextState.setSuccessTransition(successTransition); 2505 } 2506 2507 2508 Transition errorTransition = null; 2510 String errorTran = request.getParameter(STATE_ERR_TRAN); 2511 2512 2513 if (errorTran != null) { 2514 request.removeParameter(STATE_ERR_TRAN); 2515 2516 2517 try { 2518 errorTransition = Transition.fromXML(errorTran); 2519 } catch (Exception e) { 2520 throw new ControllerException(e); 2521 } 2522 } 2523 2524 2525 String stateErrorReturnController = request.getParameter(STATE_ERR_CTL); 2526 2527 2528 if (stateErrorReturnController != null) { 2529 if (errorTransition != null) { 2530 throw new ControllerException("State cannot handle stateErrorReturn Transition object " + 2531 "AND stateErrorXXX parameters in the same call."); 2532 } 2533 2534 2535 String stateErrorReturnState = request.getParameter(STATE_ERR_STATE); 2536 errorTransition = new Transition(); 2537 errorTransition.setState(stateErrorReturnState); 2538 errorTransition.setControllerObject(stateErrorReturnController); 2539 request.removeParameter(STATE_ERR_CTL); 2540 request.removeParameter(STATE_ERR_STATE); 2541 } 2542 if (errorTransition != null) { 2544 nextState.setErrorTransition(errorTransition); 2545 } 2546 } 2547 2548 2576 protected Transition processTransitions(ControllerRequest request, 2577 ControllerResponse response, 2578 State nextState) 2579 throws ControllerException, 2580 NonHandleableException { 2581 Transition successTransition = nextState.getSuccessTransition(); 2582 Transition errorTransition = nextState.getErrorTransition(); 2583 Transition chainingTransition = null; 2584 PersistentSession session = request.getSession(); 2585 String sessionKey = CTL_SUCC_TRAN + getClass().getName(); 2586 2587 2588 Transition nextTransition = null; 2590 2591 2592 if (response.hasErrors()) { 2593 nextTransition = errorTransition; } else { 2595 nextTransition = successTransition; 2596 2597 if ((nextTransition == null) && isFinalState(nextState.getName())) { 2598 if (getControllerChainingTransition() != null) { 2599 2600 2601 try { 2603 chainingTransition = (Transition) getControllerChainingTransition().clone(); 2604 } catch (CloneNotSupportedException cne) { 2605 throw new ControllerException("Cannot clone the chainingTransition class"); 2606 } 2607 2608 2609 nextTransition = chainingTransition; 2610 } else { 2611 Object successObject = null; 2612 2613 2614 try { 2615 successObject = session.getPersistentAttribute(sessionKey); 2616 } catch (NullPointerException npe) { 2618 log.debug("Invalidated Session", npe); 2619 } 2620 if (successObject != null) { 2621 String controllerSuccess = successObject.toString(); 2622 2623 2624 try { 2625 nextTransition = Transition.fromXML(controllerSuccess); 2626 } catch (Exception e) { 2627 throw new ControllerException(e); 2628 } 2629 } 2630 } 2631 } 2632 } 2633 if (nextTransition != null) { 2637 if (nextTransition == chainingTransition) { 2638 2639 String oneParamKey = ""; 2640 String oneParamValue = ""; 2641 Hashtable transitionParams = nextTransition.getParams(); 2642 for (Enumeration ep = transitionParams.keys(); ep.hasMoreElements();) { 2643 oneParamKey = (String ) ep.nextElement(); 2644 oneParamValue = (String ) transitionParams.get(oneParamKey); 2645 2646 if (oneParamValue.equals("")) { 2648 oneParamValue = request.getParameter(oneParamKey); 2649 if (oneParamValue == null) { 2650 throw new ControllerException("Required chaining parameter missing" + oneParamKey); 2651 } else { nextTransition.addParam(oneParamKey, oneParamValue); 2653 } 2654 } 2655 } 2656 2657 2658 Object successObject = null; 2659 try { 2660 successObject = session.getPersistentAttribute(sessionKey); 2661 } catch (NullPointerException npe) { 2663 log.debug("Invalidated Session", npe); 2664 } 2665 if (successObject != null) { 2666 String controllerSuccessReturn = successObject.toString(); 2667 2668 2669 nextTransition.addParam(CTL_SUCC_TRAN, 2671 controllerSuccessReturn); 2672 } 2673 } 2674 2675 2676 nextTransition.transition(request, response); 2677 2678 2679 return nextTransition; 2680 } 2681 2682 2683 return null; } 2685 2686 2698 protected void setControllerChainingTransition(Transition newControllerChainingTransition) 2699 throws NonHandleableException { 2700 if (!newControllerChainingTransition.isExternalTransition(getClass().getName())) { 2701 throw new NonHandleableException("Chained Transition must go to another controller."); 2702 } 2703 if (newControllerChainingTransition.isReturnToSenderEnabled()) { 2704 throw new NonHandleableException("Chained Transition cannot return to sender."); 2705 } 2706 2707 2708 controllerChainingTransition = newControllerChainingTransition; 2709 } 2710 2711 2721 protected void setControllerSecurityTransition(Transition newControllerSecurityTransition) { 2722 controllerSecurityTransition = newControllerSecurityTransition; 2723 } 2724 2725 2735 public ControllerResponse setCurrentState(String newState, 2736 ControllerRequest params) 2737 throws ControllerException, 2738 NonHandleableException { 2739 return newState(newState, params); 2740 } 2741 2742 2743 2748 public void setInitialState(String newInitialState) { 2749 if (!StringUtil.notNull(newInitialState).equals("")) { 2750 if (getState(newInitialState) != null) { 2751 initialStates.put(getClass().getName(), newInitialState); 2752 } else { 2753 throw new IllegalArgumentException ("Unable to set initial state " + " to '" + 2754 newInitialState + "', this is not a valid " + 2755 "state for this controller."); 2756 } 2757 } 2758 } 2759 2760 2761 2770 protected void setSchema(String schemaClass) { 2771 StringUtil.assertNotBlank(schemaClass, 2772 "Must specify a non-blank schema"); 2773 Stack stack = (Stack ) schemas.get(getClass().getName()); 2774 if (stack == null) { 2775 stack = new Stack (); 2776 stack.push(com.jcorporate.expresso.core.ExpressoSchema.class.getName()); 2778 } 2779 2780 if (!stack.contains(schemaClass)) { 2781 stack.push(schemaClass); 2782 } 2783 2784 schemas.put(getClass().getName(), stack); 2785 } 2786 2787 2788 2796 protected void setSchema(Class schemaClass) { 2797 if (schemaClass == null) { 2798 throw new IllegalArgumentException ("Parameter schemaClass must not be null"); 2799 } 2800 2801 2802 setSchema(schemaClass.getName()); 2803 } 2804 2805 2812 public void setupDefaultValues(String dbName) 2813 throws DBException { 2814 } 2815 2816 2817 2839 protected void setupReturnToSender(State nextState, 2840 ControllerRequest request) 2841 throws ControllerException { 2842 Transition returnToSender = null; 2843 String tran = request.getParameter(RETURN_TO_SENDER_TRAN); 2844 2845 2846 if (tran != null) { 2847 request.removeParameter(RETURN_TO_SENDER_TRAN); 2848 2849 2850 try { 2851 returnToSender = Transition.fromXML(tran); 2852 } catch (Exception e) { 2853 throw new ControllerException(e); 2854 } 2855 } 2856 if (returnToSender == null) { returnToSender = new Transition(); 2861 returnToSender.setState(nextState.getName()); 2862 returnToSender.setControllerObject(getClass().getName()); 2864 2865 returnToSender.setReturnToSenderParms(request); 2868 } 2869 2870 2871 nextState.setReturnToSender(returnToSender); 2872 } 2873 2874 2885 public boolean stateAllowed(String newState, ControllerRequest params) 2886 throws ControllerException { 2887 return true; 2888 } 2889 2890 2891 protected void transition(String newState, ControllerRequest req, 2892 ControllerResponse res) 2893 throws ControllerException, NonHandleableException { 2894 transition(newState, req, res, true); 2895 } 2896 2897 2907 protected void transition(String newState, Class externalController, ControllerRequest req, 2908 ControllerResponse res) 2909 throws ControllerException, NonHandleableException { 2910 2911 Transition trans = new Transition("", "", externalController, newState); 2912 trans.transition(req, res); 2913 } 2914 2915 2916 2933 protected void transition(String newState, ControllerRequest req, 2934 ControllerResponse res, boolean clear) 2935 throws ControllerException, NonHandleableException { 2936 if (log.isDebugEnabled()) { 2937 log.debug("Transitioning to state '" + newState + 2938 "' in controller '" + getClass().getName() + "'"); 2939 } 2940 2941 2942 ControllerResponse newResponse = newState(newState, req); 2943 2944 2945 if (clear) { 2946 res.clearOutputCache(); 2947 res.clearInputCache(); 2948 res.clearTransitionCache(); 2949 res.clearBlockCache(); 2950 } 2951 2952 2953 res.setDBName(newResponse.getDBName()); 2954 res.setCustomResponse(newResponse.isCustomResponse()); 2955 res.setCurrentState(newResponse.getCurrentState()); 2956 res.setStyle(newResponse.getStyle()); 2957 res.setTitle(newResponse.getTitle()); 2958 2959 Block oneBlock = null; 2960 Vector newBlocks = newResponse.getBlocks(); 2961 2962 2963 if (newBlocks != null) { 2964 for (Enumeration eb = newBlocks.elements(); eb.hasMoreElements();) { 2965 oneBlock = (Block) eb.nextElement(); 2966 oneBlock.setControllerResponse(res); 2967 res.addBlock(oneBlock); 2968 } 2969 } 2970 2971 2972 Output oneOutput = null; 2973 Vector newOutputs = newResponse.getOutputs(); 2974 2975 2976 if (newOutputs != null) { 2977 for (Enumeration eo = newOutputs.elements(); eo.hasMoreElements();) { 2978 oneOutput = (Output) eo.nextElement(); 2979 oneOutput.setControllerResponse(res); 2980 res.addOutput(oneOutput); 2981 } 2982 } 2983 2984 2985 Vector newInputs = newResponse.getInputs(); 2986 Input oneInput = null; 2987 2988 2989 if (newInputs != null) { 2990 for (Enumeration ei = newInputs.elements(); ei.hasMoreElements();) { 2991 oneInput = (Input) ei.nextElement(); 2992 oneInput.setControllerResponse(res); 2993 res.addInput(oneInput); 2994 } 2995 } 2996 2997 2998 Vector newTransitions = newResponse.getTransitions(); 2999 3000 3001 if (newTransitions != null) { 3002 Transition oneTransition = null; 3003 3004 3005 for (Enumeration et = newResponse.getTransitions().elements(); 3006 et.hasMoreElements();) { 3007 oneTransition = (Transition) et.nextElement(); 3008 oneTransition.setControllerResponse(res); 3009 res.addTransition(oneTransition); 3010 } 3011 } 3012 3013 3014 res.setControllerClass(newResponse.getControllerClass()); 3015 } 3016 3017 3018 3028 protected void unloadStateForm(StateForm stateForm, 3029 ActionForm controllerForm) 3030 throws ControllerException { 3031 if (stateForm != controllerForm) { 3032 try { BeanUtils.populate(controllerForm, 3034 BeanUtils.describe(stateForm)); 3035 } catch (Exception e) { 3036 if (com.jcorporate.expresso.core.controller.DefaultForm.class.getName() 3037 .equals(controllerForm.getClass().getName())) { 3038 return; 3039 } 3040 throw new ControllerException(e); 3041 } 3042 } 3043 } 3044 3045 3046 3054 public void redirectRequest(ControllerRequest request, 3055 ControllerResponse response, 3056 String redirectURL) 3057 throws IOException { 3058 response.setCustomResponse(true); ServletControllerRequest sr = (ServletControllerRequest) request; 3060 HttpServletResponse httpResponse = (HttpServletResponse ) sr.getServletResponse(); 3061 this.redirectRequest(httpResponse, redirectURL); 3062 } 3063 3064 3065 3074 private boolean checkSsl(HttpServletRequest aRequest, 3075 HttpServletResponse aResponse, 3076 boolean isSecure) { 3077 3078 3079 String redirectString = null; 3080 com.jcorporate.expresso.core.misc.ConfigExpresso config = 3081 ConfigManager.getConfig(); 3082 redirectString = 3083 SecureRequestUtils.getRedirectString(aRequest, 3084 config.getHttpPort(), 3085 config.getSslPort(), 3086 isSecure); 3087 3088 3089 if (redirectString != null) { 3090 try { 3091 this.redirectRequest(aResponse, redirectString); 3093 return true; 3094 } catch (java.io.IOException ioe) { 3095 log.warn("IOException in redirect: ", ioe); 3096 } 3098 } 3099 3100 3101 return false; 3102 } 3103 3104 3105 3110 public synchronized Logger getLogger() { 3111 if (mLog == null) { 3112 setupSubclassLog(); 3113 } 3114 3115 return mLog; 3116 } 3117 3118 3122 protected synchronized void setupSubclassLog() { 3123 if (mLog == null) { 3124 mLog = Logger.getLogger(getClass()); 3125 } 3126 } 3127 3128 3129 3140 protected String generateToken(ControllerRequest request) { 3141 if (request instanceof ServletControllerRequest) { 3142 ServletControllerRequest scr = (ServletControllerRequest) request; 3143 return super.generateToken((HttpServletRequest ) scr.getServletRequest()); 3144 } else { 3145 return "no-web-environment.transaction.token"; 3146 } 3147 } 3148 3149 3150 3170 protected boolean isTokenValid(ControllerRequest request) { 3171 if (request instanceof ServletControllerRequest) { 3172 ServletControllerRequest scr = (ServletControllerRequest) request; 3173 return super.isTokenValid((HttpServletRequest ) scr.getServletRequest()); 3174 } else { 3175 return true; 3177 } 3178 } 3179 3180 3181 3190 protected void resetToken(ControllerRequest request) { 3191 if (request instanceof ServletControllerRequest) { 3192 ServletControllerRequest scr = (ServletControllerRequest) request; 3193 super.resetToken(scr.getHttpServletRequest()); 3194 } 3195 } 3196 3197 3205 protected void saveToken(ControllerRequest request) { 3206 if (request instanceof ServletControllerRequest) { 3207 ServletControllerRequest scr = (ServletControllerRequest) request; 3208 super.saveToken(scr.getHttpServletRequest()); 3209 } 3210 } 3211 3212 3221 public static String [] getParamValues(ServletControllerRequest request, String paramName) { 3222 return request.getParamValues(paramName); 3223 } 3224} 3225 | Popular Tags |