1 18 19 package org.apache.struts.taglib.html; 20 21 import java.io.IOException ; 22 import java.util.ArrayList ; 23 import java.util.Collections ; 24 import java.util.Comparator ; 25 import java.util.Iterator ; 26 import java.util.List ; 27 import java.util.Locale ; 28 import java.util.Map ; 29 import java.util.StringTokenizer ; 30 31 import javax.servlet.ServletContext ; 32 import javax.servlet.http.HttpServletRequest ; 33 import javax.servlet.jsp.JspException ; 34 import javax.servlet.jsp.JspWriter ; 35 import javax.servlet.jsp.PageContext ; 36 import javax.servlet.jsp.tagext.BodyTagSupport ; 37 38 import org.apache.commons.validator.Field; 39 import org.apache.commons.validator.Form; 40 import org.apache.commons.validator.ValidatorAction; 41 import org.apache.commons.validator.ValidatorResources; 42 import org.apache.commons.validator.Var; 43 import org.apache.commons.validator.util.ValidatorUtils; 44 import org.apache.struts.Globals; 45 import org.apache.struts.action.ActionMapping; 46 import org.apache.struts.config.ModuleConfig; 47 import org.apache.struts.taglib.TagUtils; 48 import org.apache.struts.util.MessageResources; 49 import org.apache.struts.validator.Resources; 50 import org.apache.struts.validator.ValidatorPlugIn; 51 52 60 public class JavascriptValidatorTag extends BodyTagSupport { 61 62 65 private static final Comparator actionComparator = new Comparator () { 66 public int compare(Object o1, Object o2) { 67 68 ValidatorAction va1 = (ValidatorAction) o1; 69 ValidatorAction va2 = (ValidatorAction) o2; 70 71 if ((va1.getDepends() == null || va1.getDepends().length() == 0) 72 && (va2.getDepends() == null || va2.getDepends().length() == 0)) { 73 return 0; 74 75 } else if ( 76 (va1.getDepends() != null && va1.getDepends().length() > 0) 77 && (va2.getDepends() == null || va2.getDepends().length() == 0)) { 78 return 1; 79 80 } else if ( 81 (va1.getDepends() == null || va1.getDepends().length() == 0) 82 && (va2.getDepends() != null && va2.getDepends().length() > 0)) { 83 return -1; 84 85 } else { 86 return va1.getDependencyList().size() - va2.getDependencyList().size(); 87 } 88 } 89 }; 90 91 95 protected static final String HTML_BEGIN_COMMENT = "\n<!-- Begin \n"; 96 97 101 protected static final String HTML_END_COMMENT = "//End --> \n"; 102 103 105 108 protected String bundle = Globals.MESSAGES_KEY; 109 110 114 protected static Locale defaultLocale = Locale.getDefault(); 115 116 121 protected String formName = null; 122 123 130 protected String jsFormName = null; 131 132 135 protected static String lineEnd = System.getProperty("line.separator"); 136 137 141 protected int page = 0; 142 143 147 protected String methodName = null; 148 149 154 protected boolean scriptLanguage = true; 155 156 159 protected String staticJavascript = "true"; 160 161 164 protected String dynamicJavascript = "true"; 165 166 171 protected String src = null; 172 173 176 protected String htmlComment = "true"; 177 178 181 protected String cdata = "true"; 182 183 188 public String getFormName() { 189 return formName; 190 } 191 192 199 public void setFormName(String formName) { 200 this.formName = formName; 201 } 202 203 206 public String getJsFormName() { 207 return jsFormName; 208 } 209 212 public void setJsFormName(String jsFormName) { 213 this.jsFormName = jsFormName; 214 } 215 221 public int getPage() { 222 return page; 223 } 224 225 231 public void setPage(int page) { 232 this.page = page; 233 } 234 235 241 public String getMethod() { 242 return methodName; 243 } 244 245 251 public void setMethod(String methodName) { 252 this.methodName = methodName; 253 } 254 255 260 public String getStaticJavascript() { 261 return staticJavascript; 262 } 263 264 269 public void setStaticJavascript(String staticJavascript) { 270 this.staticJavascript = staticJavascript; 271 } 272 273 278 public String getDynamicJavascript() { 279 return dynamicJavascript; 280 } 281 282 287 public void setDynamicJavascript(String dynamicJavascript) { 288 this.dynamicJavascript = dynamicJavascript; 289 } 290 291 296 public String getHtmlComment() { 297 return htmlComment; 298 } 299 300 305 public void setHtmlComment(String htmlComment) { 306 this.htmlComment = htmlComment; 307 } 308 309 313 public String getSrc() { 314 return src; 315 } 316 317 322 public void setSrc(String src) { 323 this.src = src; 324 } 325 326 329 public String getBundle() { 330 return bundle; 331 } 332 333 336 public void setBundle(String bundle) { 337 this.bundle = bundle; 338 } 339 340 345 public int doStartTag() throws JspException { 346 347 JspWriter writer = pageContext.getOut(); 348 try { 349 writer.print(this.renderJavascript()); 350 351 } catch (IOException e) { 352 throw new JspException (e.getMessage()); 353 } 354 355 return EVAL_BODY_TAG; 356 357 } 358 359 363 protected String renderJavascript() throws JspException { 364 StringBuffer results = new StringBuffer (); 365 366 ModuleConfig config = TagUtils.getInstance().getModuleConfig(pageContext); 367 ValidatorResources resources = 368 (ValidatorResources) pageContext.getAttribute( 369 ValidatorPlugIn.VALIDATOR_KEY + config.getPrefix(), 370 PageContext.APPLICATION_SCOPE); 371 372 if (resources == null) { 373 throw new JspException ( 374 "ValidatorResources not found in application scope under key \"" 375 + ValidatorPlugIn.VALIDATOR_KEY + config.getPrefix() + "\""); 376 } 377 378 Locale locale = TagUtils.getInstance().getUserLocale(this.pageContext, null); 379 380 Form form = resources.getForm(locale, formName); 381 382 if ("true".equalsIgnoreCase(dynamicJavascript) && form == null) 383 { 384 throw new JspException ("No form found under '" 385 + formName 386 + "' in locale '" 387 + locale 388 + "'"); 389 } 390 391 if (form != null) { 392 if ("true".equalsIgnoreCase(dynamicJavascript)) { 393 results.append( 394 this.createDynamicJavascript(config, resources, locale, form)); 395 396 } else if ("true".equalsIgnoreCase(staticJavascript)) { 397 results.append(this.renderStartElement()); 398 if ("true".equalsIgnoreCase(htmlComment)) { 399 results.append(HTML_BEGIN_COMMENT); 400 } 401 } 402 } 403 404 if ("true".equalsIgnoreCase(staticJavascript)) { 405 results.append(getJavascriptStaticMethods(resources)); 406 } 407 408 if (form != null 409 && ("true".equalsIgnoreCase(dynamicJavascript) 410 || "true".equalsIgnoreCase(staticJavascript))) { 411 412 results.append(getJavascriptEnd()); 413 } 414 415 return results.toString(); 416 } 417 418 425 private String createDynamicJavascript( 426 ModuleConfig config, 427 ValidatorResources resources, 428 Locale locale, 429 Form form) throws JspException { 430 431 StringBuffer results = new StringBuffer (); 432 433 MessageResources messages = 434 TagUtils.getInstance().retrieveMessageResources(pageContext, bundle, true); 435 436 HttpServletRequest request = (HttpServletRequest )pageContext.getRequest(); 437 ServletContext application = pageContext.getServletContext(); 438 439 List actions = this.createActionList(resources, form); 440 441 final String methods = this.createMethods(actions, this.stopOnError(config)); 442 443 String formName = form.getName(); 444 jsFormName = formName; 445 if(jsFormName.charAt(0) == '/') { 446 String mappingName = TagUtils.getInstance().getActionMappingName(jsFormName); 447 ActionMapping mapping = (ActionMapping) config.findActionConfig(mappingName); 448 if (mapping == null) { 449 JspException e = new JspException (messages.getMessage("formTag.mapping", mappingName)); 450 pageContext.setAttribute(Globals.EXCEPTION_KEY, e, PageContext.REQUEST_SCOPE); 451 throw e; 452 } 453 jsFormName = mapping.getAttribute(); 454 } 455 456 results.append(this.getJavascriptBegin(methods)); 457 458 for (Iterator i = actions.iterator(); i.hasNext();) { 459 ValidatorAction va = (ValidatorAction) i.next(); 460 int jscriptVar = 0; 461 String functionName = null; 462 463 464 if (va.getJsFunctionName() != null 465 && va.getJsFunctionName().length() > 0) { 466 functionName = va.getJsFunctionName(); 467 } else { 468 functionName = va.getName(); 469 } 470 471 472 results.append(" function " + jsFormName + "_" + functionName + " () { \n"); 473 for (Iterator x = form.getFields().iterator(); x.hasNext();) { 474 Field field = (Field) x.next(); 475 476 if (field.isIndexed() 479 || field.getPage() != page 480 || !field.isDependency(va.getName())) { 481 482 continue; 483 } 484 485 String message = Resources.getMessage(application, 486 request, 487 messages, 488 locale, 489 va, 490 field); 491 492 message = (message != null) ? message : ""; 493 494 results.append( 496 " this.a" 497 + jscriptVar++ 498 + " = new Array(\"" 499 + field.getKey() 500 + "\", \"" 501 + escapeQuotes(message) 502 + "\", "); 503 504 results.append("new Function (\"varName\", \""); 505 506 Map vars = field.getVars(); 507 Iterator varsIterator = vars.keySet().iterator(); 509 while (varsIterator.hasNext()) { 510 String varName = (String ) varsIterator.next(); 511 Var var = (Var) vars.get(varName); 512 String varValue = var.getValue(); 513 String jsType = var.getJsType(); 514 515 if (varName.startsWith("field")) { 517 continue; 518 } 519 520 String varValueEscaped = ValidatorUtils.replace(varValue, "\\", "\\\\"); 521 varValueEscaped = ValidatorUtils.replace(varValueEscaped, "\"", "\\\""); 522 523 if (Var.JSTYPE_INT.equalsIgnoreCase(jsType)) { 524 results.append( 525 "this." 526 + varName 527 + "=" 528 + varValueEscaped 529 + "; "); 530 } else if (Var.JSTYPE_REGEXP.equalsIgnoreCase(jsType)) { 531 results.append( 532 "this." 533 + varName 534 + "=/" 535 + varValueEscaped 536 + "/; "); 537 } else if (Var.JSTYPE_STRING.equalsIgnoreCase(jsType)) { 538 results.append( 539 "this." 540 + varName 541 + "='" 542 + varValueEscaped 543 + "'; "); 544 } else if ("mask".equalsIgnoreCase(varName)) { 546 results.append( 547 "this." 548 + varName 549 + "=/" 550 + varValueEscaped 551 + "/; "); 552 } else { 553 results.append( 554 "this." 555 + varName 556 + "='" 557 + varValueEscaped 558 + "'; "); 559 } 560 } 561 562 results.append(" return this[varName];\"));\n"); 563 } 564 results.append(" } \n\n"); 565 } 566 567 return results.toString(); 568 } 569 570 private String escapeQuotes(String in) 571 { 572 if (in == null || in.indexOf("\"") == -1) 573 { 574 return in; 575 } 576 StringBuffer buffer = new StringBuffer (); 577 StringTokenizer tokenizer = new StringTokenizer (in, "\"", true); 578 579 while (tokenizer.hasMoreTokens()) 580 { 581 String token = tokenizer.nextToken(); 582 if (token.equals("\"")) 583 { 584 buffer.append("\\"); 585 } 586 buffer.append(token); 587 } 588 589 return buffer.toString(); 590 } 591 592 598 private boolean stopOnError(ModuleConfig config) { 599 Object stopOnErrorObj = 600 pageContext.getAttribute( 601 ValidatorPlugIn.STOP_ON_ERROR_KEY + '.' + config.getPrefix(), 602 PageContext.APPLICATION_SCOPE); 603 604 boolean stopOnError = true; 605 606 if (stopOnErrorObj instanceof Boolean ) { 607 stopOnError = ((Boolean ) stopOnErrorObj).booleanValue(); 608 } 609 610 return stopOnError; 611 } 612 613 620 private String createMethods(List actions, boolean stopOnError) { 621 StringBuffer methods = new StringBuffer (); 622 final String methodOperator = stopOnError ? " && " : " & "; 623 624 Iterator iter = actions.iterator(); 625 while (iter.hasNext()) { 626 ValidatorAction va = (ValidatorAction) iter.next(); 627 628 if (methods.length() > 0) { 629 methods.append(methodOperator); 630 } 631 methods.append(va.getMethod()) 632 .append("(form)"); 633 } 634 635 return methods.toString(); 636 } 637 638 644 private List createActionList(ValidatorResources resources, Form form) { 645 646 List actionMethods = new ArrayList (); 647 648 Iterator iterator = form.getFields().iterator(); 649 while (iterator.hasNext()) { 650 Field field = (Field) iterator.next(); 651 652 for (Iterator x = field.getDependencyList().iterator(); x.hasNext();) { 653 Object o = x.next(); 654 655 if (o != null && !actionMethods.contains(o)) { 656 actionMethods.add(o); 657 } 658 } 659 } 660 661 List actions = new ArrayList (); 662 663 iterator = actionMethods.iterator(); 665 while (iterator.hasNext()) { 666 String depends = (String ) iterator.next(); 667 ValidatorAction va = resources.getValidatorAction(depends); 668 669 if (va == null) { 671 throw new NullPointerException ( 672 "Depends string \"" 673 + depends 674 + "\" was not found in validator-rules.xml."); 675 } 676 677 if (va.getJavascript() != null && va.getJavascript().length() > 0) { 678 actions.add(va); 679 } else { 680 iterator.remove(); 681 } 682 } 683 684 Collections.sort(actions, actionComparator); 685 686 return actions; 687 } 688 689 692 public void release() { 693 super.release(); 694 bundle = Globals.MESSAGES_KEY; 695 formName = null; 696 jsFormName = null; 697 page = 0; 698 methodName = null; 699 staticJavascript = "true"; 700 dynamicJavascript = "true"; 701 htmlComment = "true"; 702 cdata = "true"; 703 src = null; 704 } 705 706 709 protected String getJavascriptBegin(String methods) { 710 StringBuffer sb = new StringBuffer (); 711 String name = jsFormName.replace('/', '_'); name = 713 jsFormName.substring(0, 1).toUpperCase() 714 + jsFormName.substring(1, jsFormName.length()); 715 716 sb.append(this.renderStartElement()); 717 718 if (this.isXhtml() && "true".equalsIgnoreCase(this.cdata)) { 719 sb.append("//<![CDATA[\r\n"); 720 } 721 722 if (!this.isXhtml() && "true".equals(htmlComment)) { 723 sb.append(HTML_BEGIN_COMMENT); 724 } 725 sb.append("\n var bCancel = false; \n\n"); 726 727 if (methodName == null || methodName.length() == 0) { 728 sb.append( 729 " function validate" 730 + name 731 + "(form) { \n"); 732 } else { 733 sb.append( 734 " function " 735 + methodName 736 + "(form) { \n"); 737 } 738 sb.append(" if (bCancel) \n"); 739 sb.append(" return true; \n"); 740 sb.append(" else \n"); 741 742 if (methods == null || methods.length() == 0) { 744 sb.append(" return true; \n"); 745 } else { 746 sb.append(" var formValidationResult;\n"); 748 sb.append(" formValidationResult = " + methods + "; \n"); 749 sb.append(" return (formValidationResult == 1);\n"); 750 } 751 752 sb.append(" } \n\n"); 753 754 return sb.toString(); 755 } 756 757 protected String getJavascriptStaticMethods(ValidatorResources resources) { 758 StringBuffer sb = new StringBuffer (); 759 760 sb.append("\n\n"); 761 762 Iterator actions = resources.getValidatorActions().values().iterator(); 763 while (actions.hasNext()) { 764 ValidatorAction va = (ValidatorAction) actions.next(); 765 if (va != null) { 766 String javascript = va.getJavascript(); 767 if (javascript != null && javascript.length() > 0) { 768 sb.append(javascript + "\n"); 769 } 770 } 771 } 772 773 return sb.toString(); 774 } 775 776 779 protected String getJavascriptEnd() { 780 StringBuffer sb = new StringBuffer (); 781 782 sb.append("\n"); 783 if (!this.isXhtml() && "true".equals(htmlComment)){ 784 sb.append(HTML_END_COMMENT); 785 } 786 787 if (this.isXhtml() && "true".equalsIgnoreCase(this.cdata)) { 788 sb.append("//]]>\r\n"); 789 } 790 791 sb.append("</script>\n\n"); 792 793 return sb.toString(); 794 } 795 796 801 protected String renderStartElement() { 802 StringBuffer start = new StringBuffer ("<script type=\"text/javascript\""); 803 804 if (!this.isXhtml() && this.scriptLanguage) { 806 start.append(" language=\"Javascript1.1\""); 807 } 808 809 if (this.src != null) { 810 start.append(" SRC=\"" + src + "\""); 811 } 812 813 start.append("> \n"); 814 return start.toString(); 815 } 816 817 820 private boolean isXhtml() { 821 return TagUtils.getInstance().isXhtml(this.pageContext); 822 } 823 824 828 public String getCdata() { 829 return cdata; 830 } 831 832 836 public void setCdata(String cdata) { 837 this.cdata = cdata; 838 } 839 840 846 public boolean getScriptLanguage() { 847 return this.scriptLanguage; 848 } 849 850 855 public void setScriptLanguage(boolean scriptLanguage) { 856 this.scriptLanguage = scriptLanguage; 857 } 858 859 } 860 | Popular Tags |