| 1 64 65 package com.jcorporate.expresso.core.controller; 66 67 import com.jcorporate.expresso.core.ExpressoConstants; 68 import com.jcorporate.expresso.core.misc.ConfigManager; 69 import com.jcorporate.expresso.core.misc.StringDOMParser; 70 import com.jcorporate.expresso.core.misc.StringUtil; 71 import com.jcorporate.expresso.core.misc.URLUTF8Encoder; 72 import com.jcorporate.expresso.kernel.util.FastStringBuffer; 73 import org.apache.log4j.Logger; 74 import org.apache.struts.config.ActionConfig; 75 import org.w3c.dom.Document ; 76 import org.w3c.dom.NamedNodeMap ; 77 import org.w3c.dom.Node ; 78 import org.w3c.dom.NodeList ; 79 80 import javax.servlet.RequestDispatcher ; 81 import javax.servlet.http.HttpServletRequest ; 82 import javax.servlet.http.HttpServletResponse ; 83 import java.io.IOException ; 84 import java.util.Enumeration ; 85 import java.util.Hashtable ; 86 import java.util.Map ; 87 import java.util.Vector ; 88 89 90 120 public class Transition 121 extends ControllerElement 122 implements Cloneable , 123 java.io.Serializable { 124 125 private static Logger log = Logger.getLogger(Transition.class); 126 127 130 private String ownerObject = null; 131 132 135 private String controllerObject = null; 136 137 140 private Hashtable params = new Hashtable (1); 141 private String myState = null; 142 private boolean returnToSender = false; 143 144 148 private transient String cacheParamStringSansController = null; 149 150 154 private transient String cacheParamStringWithController = null; 155 156 157 160 private transient HttpServletResponse servletResponse = null; 161 162 165 public Transition() { 166 } 167 168 175 public Transition(String newState, Controller myController) { 176 177 String className = myController.getClass().getName(); 181 myState = newState; 182 setControllerObject(className); 183 setOwnerController(className); 184 setName(newState); 185 186 Hashtable allstates = myController.getStates(); 191 State theState = null; 192 if (allstates != null) { 193 theState = (State) allstates.get(newState); 194 } 195 196 if (theState == null) { 197 throw new IllegalArgumentException ("No such state as '" + 198 newState + "' in controller '" + 199 className + 200 "'"); 201 } 202 203 setLabel(theState.getDescription()); 204 addParam(Controller.STATE_PARAM_KEY, newState); 205 } 206 207 214 public Transition(String newLabel, String newObject) { 215 super(); 216 setName(StringUtil.replace(newLabel, " ", "")); 217 setLabel(newLabel); 218 setControllerObject(newObject); 219 } 220 221 229 public Transition(String newName, String newLabel, String newObject) { 230 super(); 231 setName(newName); 232 setLabel(newLabel); 233 setControllerObject(newObject); 234 } 235 236 244 public Transition(String name, 245 String label, 246 Class controllerClass, 247 String controllerState) { 248 super(); 249 setName(name); 250 setLabel(label); 251 setControllerObject(controllerClass); 252 setState(controllerState); 253 } 254 255 263 public Transition(String label, 264 Class controllerClass, 265 String controllerState) { 266 super(); 267 setName(controllerState); 268 setLabel(label); 269 setControllerObject(controllerClass); 270 setState(controllerState); 271 } 272 273 281 public synchronized void addParam(String paramCode, String paramValue) { 282 clearCache(); 283 if (paramCode.equals(Controller.STATE_PARAM_KEY)) { 284 setState(StringUtil.notNull(paramValue)); 285 286 return; 287 } 288 if (paramCode.equals(Controller.CONTROLLER_PARAM_KEY)) { 289 setControllerObject(StringUtil.notNull(paramValue)); 290 291 return; 292 } 293 294 params.put(paramCode, StringUtil.notNull(paramValue)); 295 } 296 297 private synchronized void clearCache() { 298 cacheParamStringWithController = null; 299 cacheParamStringSansController = null; 300 } 301 302 307 public synchronized void setState(String newState) { 308 clearCache(); 309 myState = newState; 310 } 311 312 317 public String getState() { 318 if (myState == null) { 319 return getParam(Controller.STATE_PARAM_KEY); 320 } 321 322 return myState; 323 } 324 325 332 public Object clone() 333 throws CloneNotSupportedException { 334 Transition t; 335 336 synchronized (this) { 337 t = (Transition) super.clone(); 338 t.params = (Hashtable ) params.clone(); 339 t.controllerObject = controllerObject; 340 t.myState = myState; 341 t.returnToSender = returnToSender; 342 } 343 344 return t; 345 } 346 347 364 public void enableReturnToSender(ControllerResponse response) 365 throws ControllerException { 366 returnToSender = true; 367 String returnToSender = null; 368 if (response != null) { 369 FastStringBuffer fsb = FastStringBuffer.getInstance(); 370 try { 371 Transition t = response.getCurrentState().getReturnToSender(); 372 returnToSender = t.toXML(fsb).toString(); 373 } finally { 374 fsb.release(); 375 fsb = null; 376 } 377 378 if (isExternalTransition(response.getControllerClass())) { 379 if (getParam(Controller.CTL_SUCC_TRAN) == null) { addParam(Controller.CTL_SUCC_TRAN, returnToSender); 381 } 382 } else { 383 if (getParam(Controller.STATE_SUCC_TRAN) == null) { addParam(Controller.STATE_SUCC_TRAN, returnToSender); 385 } 386 } 387 } 388 } 389 390 400 public boolean isExternalTransition(String runningController) { 401 if (controllerObject == null || controllerObject.equals(runningController)) { 402 return false; 403 } else { 404 return true; 405 } 406 } 407 408 416 public String getControllerObject() { 417 if (controllerObject == null) { 418 return getParam(Controller.CONTROLLER_PARAM_KEY); 419 } 420 421 return controllerObject; 422 } 423 424 430 public String getOwnerController() { 431 return this.ownerObject; 432 } 433 434 440 public String getParam(String paramCode) { 441 return (String ) params.get(paramCode); 442 } 443 444 451 public Hashtable getParams() { 452 return params; 453 } 454 455 460 public synchronized String getParamString(boolean includeControllerParameter) { 461 if (includeControllerParameter && cacheParamStringWithController == null) { 462 FastStringBuffer paramString = FastStringBuffer.getInstance(); 463 try { 464 if (controllerObject != null) { 465 paramString.append("controller="); 466 paramString.append(controllerObject); 467 } 468 469 addNonControllerParams(paramString); 470 471 cacheParamStringWithController = paramString.toString(); 472 } finally { 473 paramString.release(); 474 paramString = null; 475 } 476 477 } 478 479 if (!includeControllerParameter && cacheParamStringSansController == null) { 480 FastStringBuffer paramString = FastStringBuffer.getInstance(); 481 try { 482 addNonControllerParams(paramString); 483 484 cacheParamStringSansController = paramString.toString(); 485 } finally { 486 paramString.release(); 487 paramString = null; 488 } 489 490 } 491 492 493 if (includeControllerParameter) { 494 return cacheParamStringWithController; 495 } else { 496 return cacheParamStringSansController; 497 } 498 499 } 500 501 private void addNonControllerParams(FastStringBuffer paramString) { 502 if (this.params != null) { 503 if (!this.params.isEmpty()) { 504 String oneKey = null; 505 506 for (Enumeration e = this.params.keys(); e.hasMoreElements();) { 507 if (paramString.length() != 0) { 508 paramString.append("&"); 509 } 510 oneKey = (String ) e.nextElement(); 511 512 FastStringBuffer fsb = FastStringBuffer.getInstance(); 515 try { 516 fsb.append(oneKey); 517 fsb.append("="); 518 fsb.append(URLUTF8Encoder.encode((String ) this.params.get(oneKey))); 519 paramString.append(fsb.toString()); 520 } finally { 521 fsb.release(); 522 fsb = null; 523 } 524 525 } 526 } 527 } 528 529 String stateString = StringUtil.notNull(getState()); 530 if (stateString.length() != 0) { 531 if (paramString.length() != 0) { 532 paramString.append("&"); 533 } 534 paramString.append("state="); 535 paramString.append(stateString); 536 } 537 } 538 539 545 public String getParamString() { 546 547 return getParamString(true); 548 549 } 550 551 566 protected ControllerResponse newStateDispatch(ControllerRequest request) 567 throws ControllerException, 568 NonHandleableException { 569 ServletControllerRequest servletRequest = (ServletControllerRequest) request; 570 HttpServletRequest httpRequest = (HttpServletRequest ) servletRequest.getServletRequest(); 571 HttpServletResponse httpResponse = (HttpServletResponse ) servletRequest.getServletResponse(); 572 ActionConfig ac = ConfigManager.getActionConfig("", controllerObject, ""); 576 577 if (ac == null) { 578 throw new ControllerException("Cannot transition to controller: " + 579 controllerObject + 580 " controller not defined in Struts configuration"); 581 } 582 583 String apath = ac.getPath(); 584 FastStringBuffer newURL = FastStringBuffer.getInstance(); 585 RequestDispatcher dispatcher = null; 586 try { 587 newURL.append(apath); 588 newURL.append(".do"); 589 newURL.append("?controller=" + getControllerObject()); 590 591 if (getState() != null) { 592 newURL.append("&state=" + getState()); 593 } 594 595 httpRequest.setAttribute(ExpressoConstants.CONTROLLER_REQUEST_KEY, request); 597 String urlValue = newURL.toString(); 598 dispatcher = httpRequest.getRequestDispatcher(urlValue); 599 600 if (dispatcher == null) { 601 throw new ControllerException("Request dispatcher was null - cannot include URL '" + 602 urlValue + "'"); 603 } 604 } finally { 605 newURL.release(); 606 newURL = null; 607 } 608 try { 609 dispatcher.include(httpRequest, httpResponse); 610 } catch (Exception e) { 611 throw new ControllerException(e); 612 } 613 614 Exception newStateException = (Exception ) httpRequest.getAttribute(ExpressoConstants.NEWSTATE_EXCEPTION_KEY); 616 617 if (newStateException != null) { if (newStateException instanceof ControllerException) { 619 throw (ControllerException) newStateException; 620 } else { 621 if (newStateException instanceof NonHandleableException) { 622 throw (NonHandleableException) newStateException; 623 } else { 624 throw (RuntimeException ) newStateException; 625 } 626 } 627 } 628 629 request = (ControllerRequest) httpRequest.getAttribute(ExpressoConstants.CONTROLLER_REQUEST_KEY); 630 httpRequest.removeAttribute(ExpressoConstants.CONTROLLER_REQUEST_KEY); 631 632 ControllerResponse response = (ControllerResponse) httpRequest.getAttribute( 633 ExpressoConstants.CONTROLLER_RESPONSE_KEY); 634 httpRequest.removeAttribute(ExpressoConstants.CONTROLLER_RESPONSE_KEY); 635 636 return response; 637 } 638 639 648 public boolean isRecursiveTransition(String runningState, 649 String runningController) { 650 String targetController = StringUtil.notNull(controllerObject); 651 String targetState = StringUtil.notNull(myState); 652 653 if (targetController.equals(runningController) && 654 targetState.equals(runningState)) { 655 return true; 656 } 657 658 return false; 659 } 660 661 666 public boolean isReturnToSenderEnabled() { 667 return returnToSender; 668 } 669 670 679 public String getHTMLParamString() { 680 String paramString = this.getParamString(); 681 paramString = URLUTF8Encoder.encode(paramString); 682 683 689 FastStringBuffer sb = FastStringBuffer.getInstance(); 690 String returnValue = null; 691 try { 692 sb.append("<input type=\"HIDDEN\" name=\""); 693 sb.append(this.getName()); 694 sb.append("_params"); 695 sb.append("\" value=\""); 696 sb.append(paramString); 697 sb.append("\">"); 698 sb.append("<input type=\"HIDDEN\" name=\""); 699 sb.append(this.getName()); 700 sb.append("_encoding"); 701 sb.append("\" value=\"u\">"); 702 returnValue = sb.toString(); 703 } finally { 704 sb.release(); 705 sb = null; 706 } 707 return returnValue; 708 } 709 710 715 public synchronized void setControllerObject(String newObject) { 716 clearCache(); 717 controllerObject = newObject; 718 } 719 720 730 public synchronized void setControllerObject(Class c) { 731 clearCache(); 732 if (c != null) { 733 setControllerObject(c.getName()); 734 } else { 735 setControllerObject((String ) null); 736 } 737 } 738 739 745 public synchronized void setOwnerController(String newController) { 746 clearCache(); 747 ownerObject = newController; 748 } 749 750 755 public synchronized void setParams(Hashtable newParams) { 756 clearCache(); 757 params = new Hashtable (newParams); 758 } 759 760 768 public synchronized void setReturnToSenderParms(ControllerRequest newReturnToSenderRequest) { 769 clearCache(); 770 String oneParamName = null; 771 Object oneParamValue = null; 772 Hashtable params = newReturnToSenderRequest.getParameters(); 773 Hashtable newParams = new Hashtable (); 774 775 for (Enumeration e = params.keys(); e.hasMoreElements();) { 781 oneParamName = (String ) e.nextElement(); 782 783 if (!oneParamName.endsWith("_params") && 784 !oneParamName.endsWith("_encoding") && 785 !oneParamName.equals(Controller.STATE_PARAM_KEY) && 786 !oneParamName.equals(Controller.CONTROLLER_PARAM_KEY)) { 787 oneParamValue = params.get(oneParamName); 788 newParams.put(oneParamName, oneParamValue); 789 } 790 } 791 792 setParams(newParams); 793 } 794 795 801 public FastStringBuffer toXML(FastStringBuffer stream) { 802 stream.append("<transition"); 803 804 if (this.getName() != null && this.getName().length() > 0) { 805 stream.append(" name=\""); 806 stream.append(StringUtil.xmlEscape(getName())); 807 stream.append("\""); 808 } 809 810 String controllerName = this.getControllerObject(); 811 812 if (controllerName != null && controllerName.length() > 0) { 813 stream.append(" controller=\""); 814 stream.append(StringUtil.xmlEscape(controllerName)); 815 stream.append("\""); 816 } 817 818 String stateName = this.getState(); 819 820 if (stateName != null && stateName.length() > 0) { 821 stream.append(" state=\""); 822 stream.append(StringUtil.xmlEscape(stateName)); 823 stream.append("\""); 824 } 825 826 stream.append(">\n"); 827 828 Hashtable params = this.getParams(); 829 String oneKey = null; 830 831 if (!params.isEmpty()) { 832 stream.append("\t<transition-parameters>\n"); 833 834 for (Enumeration ap = params.keys(); ap.hasMoreElements();) { 835 oneKey = (String ) ap.nextElement(); 836 stream.append("\t\t<transition-param name=\""); 837 stream.append(StringUtil.xmlEscape(oneKey)); 838 stream.append("\" value=\""); 839 stream.append(StringUtil.xmlEscape((String ) params.get(oneKey))); 840 stream.append("\"/>\n"); 841 } 842 843 stream.append("\t</transition-parameters>\n"); 844 } 845 846 stream = super.toXML(stream); 847 stream.append("</transition>\n"); 848 849 return stream; 850 |