1 64 65 package com.jcorporate.expresso.ext.struts.taglib; 66 67 import com.jcorporate.expresso.core.ExpressoConstants; 68 import com.jcorporate.expresso.core.controller.Block; 69 import com.jcorporate.expresso.core.controller.ControllerElement; 70 import com.jcorporate.expresso.core.controller.ControllerException; 71 import com.jcorporate.expresso.core.controller.ControllerResponse; 72 import com.jcorporate.expresso.core.controller.Input; 73 import com.jcorporate.expresso.core.controller.Output; 74 import com.jcorporate.expresso.core.controller.Transition; 75 import com.jcorporate.expresso.core.misc.StringUtil; 76 import org.apache.commons.beanutils.ConvertUtils; 77 import org.apache.commons.beanutils.PropertyUtils; 78 import org.apache.log4j.Logger; 79 80 import javax.servlet.jsp.JspException ; 81 import javax.servlet.jsp.PageContext ; 82 import java.lang.reflect.InvocationTargetException ; 83 import java.util.StringTokenizer ; 84 import java.util.Vector ; 85 86 87 92 public final class ControllerUtils { 93 private static Logger log = Logger.getLogger("expresso.ext.struts.taglib.ControllerUtils"); 94 95 96 120 public static String getBeanProperty(PageContext pageContext, String name, 121 String property, boolean ignore) 122 throws JspException { 123 126 if (!StringUtil.notNull(name).equals("")) { 127 return getSpecificBeanProperty(pageContext, name, property, ignore); 128 } 129 130 ControllerResponse myResponse = getResponse(pageContext); 131 132 if (myResponse == null) { 133 throw new JspException ("No controller response found"); 134 } 135 try { 136 if ('@' == property.charAt(0)) { 137 return myResponse.getAttribute(property.substring(1)); 138 } 139 if (property.indexOf("/") >= 0) { 140 return nestedProperty(pageContext, null, property, false); 141 } else if (property.indexOf(".") >= 0) { 142 String prefixName = property.substring(0, 143 property.indexOf(".")); 144 String propertyName = property.substring(property.indexOf(".") + 145 1); 146 147 Input i = myResponse.getInput(prefixName); 148 149 if (i != null) { 150 return inputProperty(i, propertyName, false); 151 } 152 153 Output o = myResponse.getOutput(prefixName); 154 155 if (o != null) { 156 return outputProperty(o, propertyName, false); 157 } 158 159 Transition t = myResponse.getTransition(prefixName); 160 161 if (t != null) { 162 return transitionProperty(t, propertyName, false); 163 } 164 165 Block b = myResponse.getBlock(prefixName); 166 167 if (b != null) { 168 return blockProperty(b, propertyName, false); 169 } 170 171 throw new JspException ("No input, output, block or transition named '" + 172 prefixName + "'"); 173 } else if (property.indexOf("@") >= 0) { 174 String prefixName = property.substring(0, property.indexOf("@")); 175 String propertyName = property.substring(property.indexOf("@") + 176 1); 177 178 Input i = myResponse.getInput(prefixName); 179 180 if (i != null) { 181 return inputProperty(i, propertyName, false); 182 183 184 } 185 186 Output o = myResponse.getOutput(prefixName); 187 188 if (o != null) { 189 return outputProperty(o, propertyName, false); 190 191 192 } 193 194 Transition t = myResponse.getTransition(prefixName); 195 196 if (t != null) { 197 return transitionProperty(t, propertyName, false); 198 199 200 } 201 202 Block b = myResponse.getBlock(prefixName); 203 204 if (b != null) { 205 return blockProperty(b, propertyName, false); 206 207 208 } 209 210 throw new JspException ("No input, output, block or transition named '" + 211 prefixName + "'"); 212 } 213 214 215 Output o = myResponse.getOutput(property); 216 217 if (o == null) { 218 if (ignore) { 219 return null; 220 } 221 222 throw new JspException ("No such output as '" + property + "'"); 223 } 224 225 return o.getContent(); 226 } catch (ControllerException ce) { 227 throw new JspException (ce.getMessage()); 228 } 229 } 230 231 232 238 public static final ControllerResponse getResponse(PageContext pageContext) { 239 ControllerResponse returnValue = (ControllerResponse) pageContext 240 .getAttribute(ExpressoConstants.CONTROLLER_RESPONSE_KEY, 241 PageContext.REQUEST_SCOPE); 242 if (returnValue == null) { 243 returnValue = (ControllerResponse) pageContext 244 .getAttribute(ExpressoConstants.CONTROLLER_RESPONSE_KEY, 245 PageContext.PAGE_SCOPE); 246 } 247 return returnValue; 248 } 249 250 251 262 public static String getSpecificBeanProperty(PageContext pageContext, 263 String name, String property, 264 boolean ignore) 265 throws JspException { 266 if (log.isDebugEnabled()) { 267 log.debug("Looking for bean '" + name + "', property '" + 268 StringUtil.notNull(property) + "'"); 269 } 270 if (StringUtil.notNull(property).indexOf("/") >= 0) { 271 if (log.isDebugEnabled()) { 272 log.debug("Looking for nested property '" + property + 273 "' of bean '" + StringUtil.notNull(name) + "'"); 274 } 275 276 return nestedProperty(pageContext, name, property, false); 277 } 278 279 Object obj = pageContext.getAttribute(name, PageContext.PAGE_SCOPE); 280 if (obj == null) { 281 obj = pageContext.getAttribute(name, PageContext.REQUEST_SCOPE); 282 283 if (obj == null) { 284 obj = pageContext.getAttribute(name, PageContext.SESSION_SCOPE); 285 } 286 } 287 288 ControllerElement ce = null; 289 290 if (obj instanceof ControllerElement) { 291 ce = (ControllerElement) obj; 292 if (log.isDebugEnabled()) { 293 log.debug("Bean '" + name + "' is a '" + ce.getClass().getName() + 294 "'"); 295 } 296 } else { 297 if (obj == null) { 298 return null; 299 } 300 301 return obj.toString(); 302 } 303 if (ce instanceof Output) { 304 Output o = (Output) ce; 305 306 if (property != null && property.length() > 0) { 307 return outputProperty(o, property, false); 308 } 309 310 return o.getContent(); 311 } 312 if (ce instanceof Input) { 313 Input i = (Input) ce; 314 315 if (property != null && property.length() > 0) { 316 return inputProperty(i, property, false); 317 } 318 } 319 if (ce instanceof Transition) { 320 Transition t = (Transition) ce; 321 322 if (property != null && property.length() > 0) { 323 return transitionProperty(t, property, false); 324 } 325 } 326 if (ce instanceof Block) { 327 Block b = (Block) ce; 328 329 if (property != null && property.length() > 0) { 330 return blockProperty(b, property, false); 331 } 332 } 333 334 return null; 335 } 336 337 338 350 public static boolean exists(PageContext pageContext, String name, 351 String property) 352 throws JspException { 353 if (name == null || name.length() == 0) { 354 if (property == null || property.length() == 0) { 355 throw new JspException ("Name or Property must not be null"); 356 } 357 358 if ("inputs".equals(property)) { 359 ControllerResponse res = getResponse(pageContext); 360 if (res != null) { 361 Vector v = res.getInputs(); 362 363 if (v != null) { 364 if (v.size() > 0) { 365 return true; 366 } 367 } 368 } 369 return false; 370 } else if ("outputs".equals(property)) { 371 ControllerResponse res = getResponse(pageContext); 372 if (res != null) { 373 Vector v = res.getOutputs(); 374 375 if (v != null) { 376 if (v.size() > 0) { 377 return true; 378 } 379 } 380 } 381 return false; 382 } else if ("blocks".equals(property)) { 383 ControllerResponse res = getResponse(pageContext); 384 if (res != null) { 385 Vector v = res.getBlocks(); 386 387 if (v != null) { 388 if (v.size() > 0) { 389 return true; 390 } 391 } 392 } 393 return false; 394 } else if ("transitions".equals(property)) { 395 ControllerResponse res = getResponse(pageContext); 396 if (res != null) { 397 Vector v = res.getTransitions(); 398 399 if (v != null) { 400 if (v.size() > 0) { 401 return true; 402 } 403 } 404 } 405 return false; 406 } 407 408 } 409 410 if (log.isDebugEnabled()) { 411 log.debug("Looking for element '" + StringUtil.notNull(property) + 412 "' in bean '" + StringUtil.notNull(name) + "'"); 413 } 414 415 if (StringUtil.notNull(property).indexOf("/") >= 0) { 416 if (nestedProperty(pageContext, name, property, true) != null) { 417 return true; 418 } else { 419 return false; 420 } 421 } 422 423 ControllerElement ce = findElement(pageContext, name, property); 424 425 if (ce == null) { 426 if (log.isDebugEnabled()) { 427 log.debug("No such element '" + StringUtil.notNull(property) + 428 "' in bean '" + StringUtil.notNull(name) + "'"); 429 } 430 431 return false; 432 } 433 if (name == null) { 434 if (log.isDebugEnabled()) { 435 log.debug("Name is null - returning true from exists"); 436 log.debug("Found element " + ce.getName() 437 + " matching property " + 438 property); 439 } 440 441 return true; 442 } 443 if (property == null) { 444 if (log.isDebugEnabled()) { 445 log.debug("Property is null -returning true from exists"); 446 } 447 448 return true; 449 } 450 451 if (log.isDebugEnabled()) { 452 log.debug("Property is not null - looking for property '" + property + 453 "' of '" + ce.getName() + "'"); 454 } 455 456 try { 457 if (ce.getNested(property) != null) { 458 return true; 459 } else { 460 461 462 String propVal = getSpecificBeanProperty(pageContext, name, 463 property, false); 464 465 if (propVal == null || propVal.length() == 0) { 466 return false; 467 } else { 468 return true; 469 } 470 } 471 } catch (ControllerException cee) { 472 return false; 473 } 474 } 475 476 514 public static ControllerElement interpretLeadElement( 515 PageContext pageContext, String beanExpr ) 516 throws ControllerException 517 { 518 if ( beanExpr == null ) 519 return null; 520 521 ControllerResponse controllerResponse = getResponse( pageContext ); 522 ControllerElement element = null; 523 int pos = beanExpr.indexOf(':'); 524 if ( pos >= 0 ) { 525 String scope = beanExpr.substring( 0, pos ); 526 String name = beanExpr.substring( pos+1 ); 527 if ( scope.equals("block") ) 528 element = controllerResponse.getBlock( name ); 529 else if ( scope.equals("input") ) 530 element = controllerResponse.getInput( name ); 531 else if ( scope.equals("output") ) 532 element = controllerResponse.getOutput( name ); 533 else if ( scope.equals("transition") ) 534 element = controllerResponse.getTransition( name ); 535 } 536 return element; 537 } 538 539 540 552 public static ControllerElement findElement(PageContext pageContext, 553 String name, String property) { 554 555 if ((name != null) && (name.length() > 0)) { 556 ControllerElement ce = (ControllerElement) pageContext.getAttribute(name, PageContext.PAGE_SCOPE); 557 558 if ( ce == null ) { 559 try { 560 ce = interpretLeadElement( pageContext, name ); 561 } 562 catch ( ControllerException excp ) { 563 log.error( "Failure to retrieve lead element from controller response", excp ); 564 } 565 } 566 567 568 if (property != null && property.length() > 0 && property.charAt(0) == '/') { 569 StringTokenizer stok = new StringTokenizer (property, "/"); 570 ControllerElement currentElement = ce; 571 while (stok.hasMoreTokens()) { 572 String aProperty = stok.nextToken(); 573 ControllerElement tempElement = null; 574 try { 575 tempElement = currentElement.getNested(aProperty); 576 } catch (ControllerException ex) { 577 log.error("Unable to find nested element of " + 578 currentElement.getName() + " named " + aProperty, 579 ex); 580 return null; 581 } 582 if (tempElement == null) { 583 log.error("Unable to find nested element of " + 584 currentElement.getName() + " named " + aProperty); 585 return null; 586 } 587 588 currentElement = tempElement; 589 590 } 591 return currentElement; 592 } 593 594 return ce; 595 } 596 597 ControllerResponse res = getResponse(pageContext); 598 599 try { 600 ControllerElement ce = null; 601 602 if (property != null && property.length() > 0 && property.charAt(0) == '/') { 603 StringTokenizer stok = new StringTokenizer (property, "/"); 604 ControllerElement currentElement = ce; 605 while (stok.hasMoreTokens()) { 606 String aProperty = stok.nextToken(); 607 ControllerElement tempElement = null; 608 try { 609 if (currentElement != null) { 610 tempElement = currentElement.getNested(aProperty); 611 } else { 612 tempElement = res.getBlock(aProperty); 619 620 if (tempElement == null) { 621 tempElement = res.getInput(aProperty); 622 } 623 if (tempElement == null) { 624 tempElement = res.getOutput(aProperty); 625 } 626 627 628 if (tempElement == null) { 629 tempElement = res.getTransition(aProperty); 630 } 631 632 } 633 } catch (ControllerException ex) { 634 if (currentElement == null) { 635 currentElement = new Output(); 636 currentElement.setName("<Root Element>"); 637 } 638 639 log.error("Unable to find nested element of " + 640 currentElement.getName() + " named " + aProperty, 641 ex); 642 return null; 643 } 644 645 if (tempElement == null) { 646 if (currentElement == null) { 647 currentElement = new Output(); 648 currentElement.setName("<ControllerResponse Root>"); 649 } 650 log.error("Unable to find nested element of " + 651 currentElement.getName() + " named " + aProperty); 652 return null; 653 } 654 655 currentElement = tempElement; 656 657 } 658 return currentElement; 659 } 660 661 662 663 ce = res.getInput(property); 664 665 if (ce != null) { 666 return ce; 667 } 668 669 ce = res.getOutput(property); 670 671 if (ce != null) { 672 return ce; 673 } 674 675 ce = res.getTransition(property); 676 677 if (ce != null) { 678 return ce; 679 } 680 681 ce = res.getBlock(property); 682 683 if (ce != null) { 684 return ce; 685 } 686 } catch (ControllerException ce) { 687 log.error(ce); 688 } 689 690 if (log.isDebugEnabled()) { 691 log.debug("No such ControllerElement '" + property + 692 "' in the ControllerResponse"); 693 } 694 695 return null; 696 } 697 698 705 public static Input findInput(PageContext pageContext, String property) 706 throws JspException { 707 708 709 Input myInput = null; 710 711 myInput = getResponse(pageContext).getInput(property); 712 713 if (myInput == null) { 714 throw new JspException ("No such input as '" + property + 715 "' in controller response"); 716 } 717 718 return myInput; 719 } 720 721 722 725 public static Transition findTransition(PageContext pageContext, 726 String property) 727 throws JspException { 728 729 Transition myTransition = null; 730 731 try { 732 myTransition = getResponse(pageContext).getTransition(property); 733 734 if (myTransition == null) { 735 throw new JspException ("No such transition as '" + property + 736 "' in controller response"); 737 } 738 } catch (ControllerException ce) { 739 log.error(ce); 740 throw new JspException ("Error accessing transition '" + property + 741 "':" + ce.getMessage()); 742 } 743 744 return myTransition; 745 } 746 747 748 758 public static String nestedProperty(PageContext pageContext, String name, 759 String property) 760 throws JspException { 761 String path = null; 762 763 if (property.indexOf(".") >= 0) { 764 path = property.substring(0, property.indexOf(".")); 765 } else { 766 path = property; 767 } 768 769 StringTokenizer stk = new StringTokenizer (path, "/"); 770 String oneName = null; 771 ControllerElement ce = null; 772 773 if (name != null) { 774 ce = (ControllerElement) pageContext.getAttribute(name, 775 PageContext.PAGE_SCOPE); 776 777 if (log.isDebugEnabled()) { 778 log.debug("Looking for nested property '" + 779 StringUtil.notNull(property) + "' in bean '" + name + 780 "'"); 781 } 782 } 783 while (stk.hasMoreTokens()) { 784 oneName = stk.nextToken(); 785 786 if (log.isDebugEnabled()) { 787 log.debug("Getting name '" + oneName + "'"); 788 } 789 790 if (ce == null) { 791 ce = findElement(pageContext, null, oneName); 792 793 if (ce == null) { 794 throw new JspException ("Cannot locate top element of nested chain '" + 795 property + "', no element called '" + oneName + 796 "' exists."); 797 } 798 } else { 799 800 try { 801 ce = ce.getNested(oneName); 802 } catch (ControllerException ece) { 803 log.error(ece); 804 throw new JspException ("Unable to access nested object '" + 805 oneName + "' in element '" + 806 ce.getName()); 807 } 808 if (ce == null) { 809 return null; 810 } 811 } 812 813 } 814 815 816 if (property.indexOf(".") >= 0) { 817 String suffix = property.substring(property.indexOf(".") + 1); 818 819 if (ce instanceof Output) { 820 return outputProperty((Output) ce, suffix, false); 821 } else if (ce instanceof Transition) { 822 return transitionProperty((Transition) ce, suffix, false); 823 } else if (ce instanceof Input) { 824 return inputProperty((Input) ce, suffix, false); 825 } else if (ce instanceof Block) { 826 return blockProperty((Block) ce, suffix, false); 827 } 828 } else if (property.indexOf("@") >= 0) { 829 String suffix = property.substring(property.indexOf("@") + 1); 830 831 if (ce instanceof Output) { 832 return outputProperty((Output) ce, suffix, false); 833 } else if (ce instanceof Transition) { 834 return transitionProperty((Transition) ce, suffix, false); 835 } else if (ce instanceof Input) { 836 return inputProperty((Input) ce, suffix, false); 837 } else if (ce instanceof Block) { 838 return blockProperty((Block) ce, suffix, false); 839 } 840 } 841 842 if (ce instanceof Output) { 843 Output o = (Output) ce; 844 845 return o.getContent(); 846 } else { 847 return ce.getName() + ", no contents"; 848 } 849 } 850 851 861 public static String nestedProperty(PageContext pageContext, String name, 862 String property, boolean checkExists) 863 throws JspException { 864 String path = null; 865 866 if (property.indexOf(".") >= 0) { 867 path = property.substring(0, property.indexOf(".")); 868 } else { 869 path = property; 870 } 871 872 StringTokenizer stk = new StringTokenizer (path, "/"); 873 String oneName = null; 874 ControllerElement ce = null; 875 876 if (name != null) { 877 ce = (ControllerElement) pageContext.getAttribute(name, 878 PageContext.PAGE_SCOPE); 879 880 if (log.isDebugEnabled()) { 881 log.debug("Looking for nested property '" + 882 StringUtil.notNull(property) + "' in bean '" + name + 883 "'"); 884 } 885 } 886 while (stk.hasMoreTokens()) { 887 oneName = stk.nextToken(); 888 889 if (log.isDebugEnabled()) { 890 log.debug("Getting name '" + oneName + "'"); 891 } 892 893 if (ce == null) { 894 ce = findElement(pageContext, null, oneName); 895 896 if (ce == null) { 897 throw new JspException ("Cannot locate top element of nested chain '" + 898 property + "', no element called '" + oneName + 899 "' exists."); 900 } 901 } else { 902 903 try { 904 ce = ce.getNested(oneName); 905 } catch (ControllerException ece) { 906 log.error(ece); 907 throw new JspException ("Unable to access nested object '" + 908 oneName + "' in element '" + 909 ce.getName()); 910 } 911 if (ce == null) { 912 return null; 913 } 914 } 915 916 } 917 918 919 if (property.indexOf(".") >= 0) { 920 String suffix = property.substring(property.indexOf(".") + 1); 921 922 if (ce instanceof Output) { 923 return outputProperty((Output) ce, suffix, checkExists); 924 } else if (ce instanceof Transition) { 925 return transitionProperty((Transition) ce, suffix, checkExists); 926 } else if (ce instanceof Input) { 927 return inputProperty((Input) ce, suffix, checkExists); 928 } else if (ce instanceof Block) { 929 return blockProperty((Block) ce, suffix, checkExists); 930 } 931 } else if (property.indexOf("@") >= 0) { 932 String suffix = property.substring(property.indexOf("@") + 1); 933 934 if (ce instanceof Output) { 935 return outputProperty((Output) ce, suffix, false); 936 } else if (ce instanceof Transition) { 937 return transitionProperty((Transition) ce, suffix, false); 938 } else if (ce instanceof Input) { 939 return inputProperty((Input) ce, suffix, false); 940 } else if (ce instanceof Block) { 941 return blockProperty((Block) ce, suffix, false); 942 } 943 } 944 945 if (ce instanceof Output) { 946 Output o = (Output) ce; 947 948 return o.getContent(); 949 } else { 950 return ce.getName() + ", no contents"; 951 } 952 } 953 954 955 private static String blockProperty(Block b, String propName, boolean checkExists) 956 throws JspException { 957 958 String propValue = elementProperty(b, propName); 959 if ('@' == propName.charAt(0) && propValue == null) { 960 if (checkExists) { 961 return null; 962 } 963 propValue = ""; 964 } 965 966 if (propValue != null) { 967 return propValue; 968 } 969 970 if (propName.equals("type")) { 971 return "block"; 972 } 973 974 throw new JspException ("No such property as '" + propName + 975 "' in Block '" + b.getName() + "'"); 976 977 } 978 979 private static String elementProperty(ControllerElement ce, 980 String propName) { 981 982 if ('@' == (propName.charAt(0))) { 983 return (String ) ce.getAttribute(propName.substring(1)); 984 } 985 986 if (propName.equals("label")) { 987 return ce.getLabel(); 988 } else if (propName.equals("description")) { 989 return ce.getDescription(); 990 } else if (propName.equals("name")) { 991 return ce.getName(); 992 } else if (propName.equals("defaultValue") && ce instanceof Input) { 993 return ((Input) ce).getDefaultValue(); 994 } 995 996 return null; 997 } 998 999 1008 private static String inputProperty(Input i, String propName, boolean checkExists) 1009 throws JspException { 1010 1011 String propValue = elementProperty(i, propName); 1012 if ('@' == propName.charAt(0) && propValue == null) { 1013 if (checkExists) { 1014 return null; 1015 } 1016 propValue = ""; 1017 } 1018 1019 if (propValue != null) { 1020 return propValue; 1021 } 1022 1023 if (propName.equals("type")) { 1024 return "input"; 1025 } else if (propName.equals("defaultValue")) { 1026 return i.getDefaultValue(); 1027 } 1028 throw new JspException ("No such property as '" + propName + 1029 "' in Input '" + i.getName() + "'"); 1030 1031 } 1032 1033 1034 private static String outputProperty(Output o, String propName, boolean checkExists) 1035 throws JspException { 1036 1037 String propValue = elementProperty(o, propName); 1038 if ('@' == propName.charAt(0) && propValue == null) { 1039 if (checkExists) { 1040 return null; 1041 } 1042 propValue = ""; 1043 } 1044 1045 if (propValue != null) { 1046 return propValue; 1047 } 1048 1049 if (propName.equals("type")) { 1050 return "output"; 1051 } 1052 1053 throw new JspException ("No such property as '" + propName + 1054 "' in Output '" + o.getName() + "'"); 1055 1056 } 1057 1058 1059 private static String transitionProperty(Transition t, String propName, boolean checkExists) 1060 throws JspException { 1061 try { 1062 if (log.isDebugEnabled()) { 1063 log.debug("Looking for property '" + propName + 1064 "' from transition '" + t.getName() + "'"); 1065 } 1066 1067 String propValue = elementProperty(t, propName); 1068 if ('@' == propName.charAt(0) && propValue == null) { 1069 if (checkExists) { 1070 return null; 1071 } 1072 propValue = ""; 1073 } 1074 1075 if (propValue != null) { 1076 return propValue; 1077 } 1078 1079 if (propName.equals("type")) { 1080 return "transition"; 1081 } else if (propName.equals("url")) { 1082 return t.getUrl(); 1083 } else if (propName.equals("params")) { 1084 return t.getParamString(); 1085 } 1086 1087 try { 1091 return (String ) ConvertUtils.convert(PropertyUtils.getProperty(t, propName)); 1092 } catch (IllegalAccessException ex) { 1093 throw new JspException ("Property '" + propName + 1094 "' in Transition '" + t.getName() + 1095 "' exists, but is not 'public'"); 1096 } catch (NoSuchMethodException ex) { 1097 throw new JspException ("No such property as '" + propName + 1098 "' in Transition '" + t.getName() + "'"); 1099 } 1100 1101 } catch (InvocationTargetException ex) { 1102 log.error(ex); 1103 throw new JspException ("Unable to access property from Transition:" + 1104 ex.getMessage()); 1105 } catch (ControllerException ce) { 1106 log.error(ce); 1107 throw new JspException ("Unable to access property from Transition:" + 1108 ce.getMessage()); 1109 } 1110 } 1111 1112} 1113 1114 | Popular Tags |