001 package railo.transformer.library.tag; 002 003 import java.io.IOException; 004 import java.lang.reflect.Constructor; 005 import java.lang.reflect.InvocationTargetException; 006 import java.util.HashMap; 007 import java.util.Iterator; 008 import java.util.LinkedHashMap; 009 import java.util.Map; 010 import java.util.Map.Entry; 011 012 import org.objectweb.asm.Type; 013 014 import railo.commons.lang.ClassException; 015 import railo.commons.lang.ClassUtil; 016 import railo.commons.lang.Md5; 017 import railo.commons.lang.StringUtil; 018 import railo.runtime.op.Caster; 019 import railo.transformer.bytecode.Position; 020 import railo.transformer.bytecode.cast.CastOther; 021 import railo.transformer.bytecode.expression.Expression; 022 import railo.transformer.bytecode.literal.LitBoolean; 023 import railo.transformer.bytecode.literal.LitDouble; 024 import railo.transformer.bytecode.literal.LitString; 025 import railo.transformer.bytecode.statement.tag.Attribute; 026 import railo.transformer.bytecode.statement.tag.Tag; 027 import railo.transformer.bytecode.statement.tag.TagOther; 028 import railo.transformer.cfml.attributes.AttributeEvaluator; 029 import railo.transformer.cfml.attributes.AttributeEvaluatorException; 030 import railo.transformer.cfml.evaluator.Evaluator; 031 import railo.transformer.cfml.evaluator.EvaluatorException; 032 import railo.transformer.cfml.tag.TagDependentBodyTransformer; 033 034 /** 035 * Die Klasse TagLibTag repaesentiert ein einzelne Tag Definition einer TagLib, 036 * beschreibt also alle Informationen die man zum validieren eines Tags braucht. 037 */ 038 public final class TagLibTag { 039 040 public final static int ATTRIBUTE_TYPE_FIXED=0; 041 public final static int ATTRIBUTE_TYPE_DYNAMIC=1; 042 public final static int ATTRIBUTE_TYPE_NONAME=3; 043 public final static int ATTRIBUTE_TYPE_MIXED=4; 044 045 046 /** 047 * Definition des Attribut Type 048 */ 049 //public final static int ATTRIBUTE_TYPE_FULLDYNAMIC=2; deprecated 050 /** 051 * Definition des Attribut Type 052 */ 053 054 private final static Class[] CONSTRUCTOR_PARAMS=new Class[]{Position.class,Position.class}; 055 056 private int attributeType; 057 private String name; 058 private boolean hasBody=true; 059 060 private boolean isBodyReq=false; 061 private boolean isTagDependent=false; 062 private boolean bodyFree=true; 063 064 private boolean parseBody; 065 private boolean hasAppendix; 066 private String description=""; 067 private String tagClass; 068 private String tteClass; 069 private String tdbtClass; 070 private int min; 071 private int max; 072 private TagLib tagLib; 073 private Evaluator eval; 074 private TagDependentBodyTransformer tdbt; 075 076 private Map<String,TagLibTagAttr> attributes=new LinkedHashMap<String,TagLibTagAttr>(); 077 private Map<String,String> setters=new HashMap<String,String>(); 078 private TagLibTagAttr attrFirst; 079 private TagLibTagAttr attrLast; 080 081 private String strAttributeEvaluator; 082 private AttributeEvaluator attributeEvaluator; 083 private boolean handleException; 084 private boolean hasDefaultValue=false; 085 private Type tagType; 086 private String tttClass; 087 private Constructor tttConstructor; 088 private boolean allowRemovingLiteral; 089 private TagLibTagAttr defaultAttribute; 090 private short status=TagLib.STATUS_IMPLEMENTED; 091 private Class clazz; 092 private TagLibTagScript script; 093 private final static TagLibTagAttr UNDEFINED=new TagLibTagAttr(null); 094 private TagLibTagAttr singleAttr=UNDEFINED; 095 private Expression attributeDefaultValue; 096 097 public TagLibTag duplicate(boolean cloneAttributes) { 098 TagLibTag tlt = new TagLibTag(tagLib); 099 100 tlt.attributeType=attributeType; 101 tlt.name=name; 102 tlt.hasBody=hasBody; 103 tlt.isBodyReq=isBodyReq; 104 tlt.isTagDependent=isTagDependent; 105 tlt.bodyFree=bodyFree; 106 tlt.parseBody=parseBody; 107 tlt.hasAppendix=hasAppendix; 108 tlt.description=description; 109 tlt.tagClass=tagClass; 110 tlt.tteClass=tteClass; 111 tlt.tdbtClass=tdbtClass; 112 tlt.min=min; 113 tlt.max=max; 114 tlt.strAttributeEvaluator=strAttributeEvaluator; 115 tlt.handleException=handleException; 116 tlt.hasDefaultValue=hasDefaultValue; 117 tlt.tagType=tagType; 118 tlt.tttClass=tttClass; 119 tlt.tttConstructor=tttConstructor; 120 tlt.allowRemovingLiteral=allowRemovingLiteral; 121 tlt.status=status; 122 123 tlt.eval=null; 124 tlt.tdbt=null; 125 tlt.attributeEvaluator=null; 126 127 128 Iterator<Entry<String, TagLibTagAttr>> it = attributes.entrySet().iterator(); 129 if(cloneAttributes) { 130 while(it.hasNext()){ 131 tlt.setAttribute(it.next().getValue().duplicate(tlt)); 132 } 133 if(defaultAttribute!=null)tlt.defaultAttribute=defaultAttribute.duplicate(tlt); 134 } 135 else { 136 while(it.hasNext()){ 137 tlt.setAttribute(it.next().getValue()); 138 tlt.attrFirst=attrFirst; 139 tlt.attrLast=attrLast; 140 } 141 tlt.defaultAttribute=defaultAttribute; 142 } 143 144 145 // setter 146 Iterator<Entry<String, String>> sit = setters.entrySet().iterator(); 147 Entry<String, String> se; 148 while(sit.hasNext()){ 149 se = sit.next(); 150 tlt.setters.put(se.getKey(), se.getValue()); 151 } 152 153 154 155 /* 156 private Map attributes=new HashMap(); 157 private TagLibTagAttr attrFirst; 158 private TagLibTagAttr attrLast; 159 160 private Map setters=new HashMap(); 161 private TagLibTagAttr defaultAttribute; 162 */ 163 return tlt; 164 } 165 166 167 /** 168 * Geschuetzer Konstruktor ohne Argumente. 169 * @param tagLib 170 */ 171 public TagLibTag(TagLib tagLib) { 172 this.tagLib=tagLib; 173 } 174 175 /** 176 * Gibt alle Attribute (TagLibTagAttr) eines Tag als HashMap zurueck. 177 * @return HashMap Attribute als HashMap. 178 */ 179 public Map<String,TagLibTagAttr> getAttributes() { 180 return attributes; 181 } 182 183 /** 184 * Gibt ein bestimmtes Attribut anhand seines Namens zurueck, 185 * falls dieses Attribut nicht existiert wird null zurueckgegeben. 186 * @param name Name des Attribut das zurueckgegeben werden soll. 187 * @return Attribute das angfragt wurde oder null. 188 */ 189 public TagLibTagAttr getAttribute(String name) { 190 return attributes.get(name); 191 } 192 193 194 195 196 /** 197 * Gibt das erste Attribut, welches innerhalb des Tag definiert wurde, zurueck. 198 * @return Attribut das angfragt wurde oder null. 199 */ 200 public TagLibTagAttr getFirstAttribute() { 201 return attrFirst; 202 } 203 204 /** 205 * Gibt das letzte Attribut, welches innerhalb des Tag definiert wurde, zurueck. 206 * @return Attribut das angfragt wurde oder null. 207 */ 208 public TagLibTagAttr getLastAttribute() { 209 return attrLast; 210 } 211 212 /** 213 * Gibt den Namen des Tag zurueck. 214 * @return String Name des Tag. 215 */ 216 public String getName() { 217 return name; 218 } 219 220 /** 221 * Gibt den kompletten Namen des Tag zurueck, inkl. Name-Space und Trenner. 222 * @return String Kompletter Name des Tag. 223 */ 224 public String getFullName() { 225 String fullName; 226 if(tagLib!=null) { 227 fullName=tagLib.getNameSpaceAndSeparator()+name; 228 } 229 else { 230 fullName=name; 231 } 232 return fullName; 233 } 234 235 /** 236 * Gibt die Klassendefinition, welche diesen Tag implementiert, als Zeichenkette zurueck. 237 * Achtung: Die implementierende Klasse ist keine Java Klasse. 238 * @return String Zeichenkette der Klassendefinition. 239 */ 240 public String getTagClassName() { 241 return tagClass; 242 } 243 244 245 public Class getClazz() throws ClassException { 246 if(clazz==null) { 247 clazz=ClassUtil.loadClass(tagClass); 248 } 249 return clazz; 250 } 251 252 253 public Type getTagType() throws ClassException { 254 if(tagType==null) { 255 tagType=Type.getType(getClazz()); 256 } 257 return tagType; 258 } 259 /** 260 * @return the status (TagLib.,TagLib.STATUS_IMPLEMENTED,TagLib.STATUS_DEPRECATED,TagLib.STATUS_UNIMPLEMENTED) 261 */ 262 public short getStatus() { 263 return status; 264 } 265 266 267 /** 268 * @param status the status to set (TagLib.,TagLib.STATUS_IMPLEMENTED,TagLib.STATUS_DEPRECATED,TagLib.STATUS_UNIMPLEMENTED) 269 */ 270 public void setStatus(short status) { 271 this.status = status; 272 } 273 274 /** 275 * Gibt die Klassendefinition, der Klasse die den Evaluator (Translation Time Evaluator) implementiert, 276 * als Zeichenkette zurueck. 277 * Falls kein Evaluator definiert ist wird null zurueckgegeben. 278 * @return String Zeichenkette der Klassendefinition. 279 */ 280 public String getTteClassName() { 281 return tteClass; 282 } 283 284 public String getTttClassName() { 285 return tttClass; 286 } 287 288 /** 289 * Gibt den Evaluator (Translation Time Evaluator) dieser Klasse zurueck. 290 * Falls kein Evaluator definiert ist, wird null zurueckgegeben. 291 * @return Implementation des Evaluator zu dieser Klasse. 292 * @throws EvaluatorException Falls die Evaluator-Klasse nicht geladen werden kann. 293 */ 294 public Evaluator getEvaluator() throws EvaluatorException { 295 if(!hasTteClass()) return null; 296 if(eval!=null) return eval; 297 try { 298 eval = (Evaluator) ClassUtil.loadInstance(tteClass); 299 } 300 catch (ClassException e) { 301 throw new EvaluatorException(e.getMessage()); 302 } 303 return eval; 304 } 305 306 /** 307 * Gibt den TagDependentBodyTransformer dieser Klasse zurueck. 308 * Falls kein TagDependentBodyTransformer definiert ist, wird null zurueckgegeben. 309 * @return Implementation des TagDependentBodyTransformer zu dieser Klasse. 310 * @throws TagLibException Falls die TagDependentBodyTransformer-Klasse nicht geladen werden kann. 311 */ 312 public TagDependentBodyTransformer getBodyTransformer() throws TagLibException { 313 if(!hasTdbtClass()) return null; 314 if(tdbt!=null) return tdbt; 315 try { 316 tdbt = (TagDependentBodyTransformer) ClassUtil.loadInstance(tdbtClass); 317 } catch (ClassException e) { 318 throw new TagLibException(e); 319 } 320 return tdbt; 321 } 322 323 /** 324 * Gibt zurueck ob Exception durch die implementierte Klasse abgehandelt werden oder nicht 325 * @return Wird eine Exception abgehandelt? 326 */ 327 public boolean handleException() { 328 return handleException; 329 } 330 331 /** 332 * Gibt zurueck, ob eine Klassendefinition 333 * der Klasse die den Evaluator (Translation Time Evaluator) implementiert existiert. 334 * @return Ob eine Evaluator definiert ist. 335 */ 336 public boolean hasTteClass() { 337 return tteClass !=null && tteClass.length()>0; 338 } 339 340 /** 341 * Gibt zurueck, ob eine Klassendefinition 342 * der Klasse die den TagDependentBodyTransformer implementiert existiert. 343 * @return Ob eine Evaluator definiert ist. 344 */ 345 public boolean hasTdbtClass() { 346 return tdbtClass !=null && tdbtClass.length()>0; 347 } 348 349 /** 350 * Gibt den Attributetyp der Klasse zurueck. 351 * ( ATTRIBUTE_TYPE_FIX, ATTRIBUTE_TYPE_DYNAMIC, ATTRIBUTE_TYPE_NONAME) 352 * @return int 353 */ 354 public int getAttributeType() { 355 return attributeType; 356 } 357 358 /** 359 * Gibt zurueck, ob das Tag einen Body haben kann oder nicht. 360 * @return Kann das Tag einen Body haben. 361 */ 362 public boolean getHasBody() { 363 return hasBody; 364 } 365 366 /** 367 * Gibt die maximale Anzahl Attribute zurueck, die das Tag haben kann. 368 * @return Maximale moegliche Anzahl Attribute. 369 */ 370 public int getMax() { 371 return max; 372 } 373 374 /** 375 * Gibt die minimale Anzahl Attribute zurueck, die das Tag haben muss. 376 * @return Minimal moegliche Anzahl Attribute. 377 */ 378 public int getMin() { 379 return min; 380 } 381 382 /** 383 * Gibt die TagLib zurueck zu der das Tag gehoert. 384 * @return TagLib Zugehoerige TagLib. 385 */ 386 public TagLib getTagLib() { 387 return tagLib; 388 } 389 390 /** 391 * Gibt zurueck ob das Tag seinen Body parsen soll oder nicht. 392 * @return Soll der Body geparst werden. 393 */ 394 public boolean getParseBody() { 395 return parseBody; 396 } 397 398 /** 399 * Gibt zurueck, ob das Tag einen Appendix besitzen kann oder nicht. 400 * @return Kann das Tag einen Appendix besitzen. 401 */ 402 public boolean hasAppendix() { 403 return hasAppendix; 404 } 405 406 /** 407 * Fragt ab ob der Body eines Tag freiwillig ist oder nicht. 408 * @return is required 409 */ 410 public boolean isBodyReq() { 411 return isBodyReq; 412 } 413 414 /** 415 * Fragt ab ob die verarbeitung des Inhaltes eines Tag mit einem eigenen Transformer 416 * vorgenommen werden soll. 417 * @return Fragt ab ob die verarbeitung des Inhaltes eines Tag mit einem eigenen Transformer 418 * vorgenommen werden soll. 419 */ 420 public boolean isTagDependent() { 421 return isTagDependent; 422 } 423 424 /** 425 * Setzt die TagLib des Tag. 426 * Diese Methode wird durch die Klasse TagLibFactory verwendet. 427 * @param tagLib TagLib des Tag. 428 */ 429 protected void setTagLib(TagLib tagLib) { 430 this.tagLib = tagLib; 431 } 432 433 /** 434 * Setzt ein einzelnes Attribut (TagLibTagAttr) eines Tag. 435 * Diese Methode wird durch die Klasse TagLibFactory verwendet. 436 * @param attribute Attribute eines Tag. 437 */ 438 public void setAttribute(TagLibTagAttr attribute) { 439 attributes.put(attribute.getName(),attribute); 440 if(attrFirst==null)attrFirst=attribute; 441 attrLast=attribute; 442 } 443 444 /** 445 * Setzt den Attributtyp eines Tag. 446 * ( ATTRIBUTE_TYPE_FIX, ATTRIBUTE_TYPE_DYNAMIC, ATTRIBUTE_TYPE_FULLDYNAMIC, ATTRIBUTE_TYPE_NONAME) 447 * Diese Methode wird durch die Klasse TagLibFactory verwendet. 448 * @param attributeType The attributeType to set 449 */ 450 public void setAttributeType(int attributeType) { 451 452 this.attributeType = attributeType; 453 } 454 455 /** 456 * Setzt die Information, was fuer ein BodyContent das Tag haben kann. 457 * Diese Methode wird durch die Klasse TagLibFactory verwendet. 458 * @param value BodyContent Information. 459 */ 460 public void setBodyContent(String value) { 461 // empty, free, must, tagdependent 462 value=value.toLowerCase().trim(); 463 //if(value.equals("jsp")) value="free"; 464 465 this.hasBody = !value.equals("empty"); 466 this.isBodyReq = !value.equals("free"); 467 this.isTagDependent = value.equals("tagdependent"); 468 bodyFree=value.equals("free"); 469 } 470 471 /** 472 * Setzt wieviele Attribute das Tag maximal haben darf. 473 * Diese Methode wird durch die Klasse TagLibFactory verwendet. 474 * @param max The max to set 475 */ 476 protected void setMax(int max) { 477 this.max = max; 478 } 479 480 /** 481 * Setzt wieviele Attribute das Tag minimal haben darf. 482 * Diese Methode wird durch die Klasse TagLibFactory verwendet. 483 * @param min The min to set 484 */ 485 protected void setMin(int min) { 486 this.min = min; 487 } 488 489 /** 490 * Setzt den Namen des Tag. 491 * Diese Methode wird durch die Klasse TagLibFactory verwendet. 492 * @param name Name des Tag. 493 */ 494 public void setName(String name) { 495 this.name = name.toLowerCase(); 496 } 497 498 /** 499 * Setzt die implementierende Klassendefinition des Tag. 500 * Diese Methode wird durch die Klasse TagLibFactory verwendet. 501 * @param tagClass Klassendefinition der Tag-Implementation. 502 */ 503 public void setTagClass(String tagClass) { 504 this.tagClass = tagClass; 505 } 506 507 /** 508 * Setzt die implementierende Klassendefinition des Evaluator. 509 * Diese Methode wird durch die Klasse TagLibFactory verwendet. 510 * @param tteClass Klassendefinition der Evaluator-Implementation. 511 */ 512 protected void setTteClass(String tteClass) { 513 this.tteClass = tteClass; 514 } 515 516 /** 517 * Setzt die implementierende Klassendefinition des Evaluator. 518 * Diese Methode wird durch die Klasse TagLibFactory verwendet. 519 * @param tteClass Klassendefinition der Evaluator-Implementation. 520 */ 521 public void setTttClass(String tttClass) { 522 this.tttClass = tttClass; 523 this.tttConstructor=null; 524 } 525 526 /** 527 * Setzt die implementierende Klassendefinition des TagDependentBodyTransformer. 528 * Diese Methode wird durch die Klasse TagLibFactory verwendet. 529 * @param tdbtClass Klassendefinition der TagDependentBodyTransformer-Implementation. 530 */ 531 public void setTdbtClass(String tdbtClass) { 532 this.tdbtClass = tdbtClass; 533 this.tdbt = null; 534 } 535 536 /** 537 * Setzt, ob der Body des Tag geparst werden soll oder nicht. 538 * Diese Methode wird durch die Klasse TagLibFactory verwendet. 539 * @param parseBody Soll der Body geparst werden. 540 */ 541 public void setParseBody(boolean parseBody) { 542 this.parseBody = parseBody; 543 } 544 545 /** 546 * Setzt ob das Tag einen Appendix besitzen kann oder nicht. 547 * Diese Methode wird durch die Klasse TagLibFactory verwendet. 548 * @param hasAppendix Kann das Tag einen Appendix besitzen. 549 */ 550 public void setAppendix(boolean hasAppendix) { 551 this.hasAppendix = hasAppendix; 552 } 553 /** 554 * @return Returns the description. 555 */ 556 public String getDescription() { 557 return description; 558 } 559 560 /** 561 * @param description The description to set. 562 */ 563 public void setDescription(String description) { 564 this.description = description; 565 } 566 567 /** 568 * @return Returns the bodyIsFree. 569 */ 570 public boolean isBodyFree() { 571 return bodyFree; 572 } 573 574 public boolean hasBodyMethodExists() { 575 Class clazz= ClassUtil.loadClass(getTagClassName(),(Class)null);//Class.orName(tag.getTagClassName()); 576 if(clazz==null) return false; 577 578 try { 579 java.lang.reflect.Method method = clazz.getMethod("hasBody", new Class[]{boolean.class}); 580 if(method==null)return false; 581 return method.getReturnType()==void.class; 582 } 583 catch (Exception e) {} 584 return false; 585 } 586 587 /** 588 * @return Gibt zurueck ob ein Attribut Evaluator definiert ist oder nicht. 589 */ 590 public boolean hasAttributeEvaluator() { 591 return strAttributeEvaluator!=null; 592 } 593 594 /** 595 * @return Gibt den AttributeEvaluator zum Tag zurueck 596 * @throws AttributeEvaluatorException 597 */ 598 public AttributeEvaluator getAttributeEvaluator() throws AttributeEvaluatorException { 599 if(!hasAttributeEvaluator()) return null; 600 if(attributeEvaluator!=null) return attributeEvaluator; 601 try { 602 return attributeEvaluator=(AttributeEvaluator) ClassUtil.loadInstance(strAttributeEvaluator); 603 604 } catch (ClassException e) { 605 throw new AttributeEvaluatorException(e.getMessage()); 606 } 607 } 608 609 /** 610 * Setzt den Namen der Klasse welche einen AttributeEvaluator implementiert. 611 * @param value Name der AttributeEvaluator Klassse 612 */ 613 public void setAttributeEvaluatorClassName(String value) { 614 strAttributeEvaluator=value; 615 616 } 617 618 /** 619 * sets if tag handle exception inside his body or not 620 * @param handleException handle it or not 621 */ 622 public void setHandleExceptions(boolean handleException) { 623 this.handleException=handleException; 624 } 625 626 /** 627 * @return 628 */ 629 public boolean hasDefaultValue() { 630 return hasDefaultValue; 631 } 632 633 /** 634 * @param hasDefaultValue The hasDefaultValue to set. 635 */ 636 public void setHasDefaultValue(boolean hasDefaultValue) { 637 this.hasDefaultValue = hasDefaultValue; 638 } 639 640 /** 641 * return ASM Tag for this tag 642 * @param line 643 * @return 644 645 */ 646 public Tag getTag(Position start,Position end) throws TagLibException { 647 if(StringUtil.isEmpty(tttClass)) return new TagOther(start,end); 648 try { 649 return _getTag(start,end); 650 } 651 catch (ClassException e) { 652 throw new TagLibException(e.getMessage()); 653 } 654 catch (NoSuchMethodException e) { 655 throw new TagLibException(e.getMessage()); 656 } 657 catch (Throwable e) { 658 throw new TagLibException(e); 659 } 660 } 661 private Tag _getTag(Position start,Position end) throws ClassException, SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException { 662 if(tttConstructor==null) { 663 Class clazz = ClassUtil.loadClass(tttClass); 664 tttConstructor = clazz.getConstructor(CONSTRUCTOR_PARAMS); 665 } 666 return (Tag) tttConstructor.newInstance(new Object[]{start,end}); 667 } 668 669 public void setAllowRemovingLiteral(boolean allowRemovingLiteral) { 670 this.allowRemovingLiteral=allowRemovingLiteral; 671 } 672 673 /** 674 * @return the allowRemovingLiteral 675 */ 676 public boolean isAllowRemovingLiteral() { 677 return allowRemovingLiteral; 678 } 679 680 public String getAttributeNames() { 681 Iterator<String> it = attributes.keySet().iterator(); 682 StringBuffer sb=new StringBuffer(); 683 while(it.hasNext()) { 684 if(sb.length()>0)sb.append(","); 685 sb.append(it.next()); 686 } 687 return sb.toString(); 688 } 689 690 public String getSetter(Attribute attr, Type type) { 691 if(tagLib.isCore()) 692 return "set"+StringUtil.ucFirst(attr.getName()); 693 694 String setter=setters.get(attr.getName()); 695 if(setter!=null)return setter; 696 setter = "set"+StringUtil.ucFirst(attr.getName()); 697 Class clazz; 698 try { 699 if(type==null) type = CastOther.getType(attr.getType()); 700 clazz=ClassUtil.loadClass(getTagClassName()); 701 java.lang.reflect.Method m = ClassUtil.getMethodIgnoreCase(clazz,setter,new Class[]{ClassUtil.loadClass(type.getClassName())}); 702 setter=m.getName(); 703 } 704 catch (Exception e) { 705 //print.err(setter); 706 e.printStackTrace(); 707 } 708 setters.put(attr.getName(), setter); 709 return setter; 710 } 711 712 public String getHash() { 713 StringBuffer sb=new StringBuffer(); 714 sb.append(this.getTagClassName()); 715 sb.append(this.getAttributeNames()); 716 sb.append(this.getAttributeType()); 717 sb.append(this.getMax()); 718 sb.append(this.getMin()); 719 sb.append(this.getName()); 720 sb.append(this.getParseBody()); 721 sb.append(this.getTteClassName()); 722 sb.append(this.getTttClassName()); 723 Iterator<Entry<String, TagLibTagAttr>> it = this.getAttributes().entrySet().iterator(); 724 Entry<String, TagLibTagAttr> entry; 725 while(it.hasNext()){ 726 entry = it.next(); 727 sb.append(entry.getKey()); 728 sb.append(entry.getValue().getHash()); 729 } 730 731 try { 732 return Md5.getDigestAsString(sb.toString()); 733 } catch (IOException e) { 734 return ""; 735 } 736 } 737 738 public TagLibTagAttr getDefaultAttribute() { 739 return defaultAttribute; 740 } 741 742 public void setDefaultAttribute(TagLibTagAttr defaultAttribute) { 743 this.defaultAttribute=defaultAttribute; 744 } 745 746 747 public void setScript(TagLibTagScript script) { 748 this.script=script; 749 } 750 751 752 /** 753 * @return the script 754 */ 755 public TagLibTagScript getScript() { 756 return script; 757 } 758 759 760 public TagLibTagAttr getSingleAttr() { 761 762 if(singleAttr==UNDEFINED) { 763 singleAttr=null; 764 Iterator<TagLibTagAttr> it = getAttributes().values().iterator(); 765 TagLibTagAttr attr; 766 while(it.hasNext()){ 767 attr=it.next(); 768 if(attr.getNoname()){ 769 singleAttr=attr; 770 break; 771 } 772 } 773 } 774 return singleAttr; 775 } 776 777 778 /** 779 * attribute value set, if the attribute has no value defined 780 * @return 781 */ 782 public Expression getAttributeDefaultValue() { 783 if(attributeDefaultValue==null) return LitBoolean.TRUE; 784 return attributeDefaultValue; 785 } 786 787 public void setAttributeDefaultValue(String defaultValue) { 788 defaultValue=defaultValue.trim(); 789 // boolean 790 if(StringUtil.startsWithIgnoreCase(defaultValue, "boolean:")) { 791 String str=defaultValue.substring(8).trim(); 792 Boolean b = Caster.toBoolean(str,null); 793 if(b!=null){ 794 this.attributeDefaultValue=LitBoolean.toExprBoolean(b.booleanValue()); 795 return; 796 } 797 798 } 799 // number 800 else if(StringUtil.startsWithIgnoreCase(defaultValue, "number:")) { 801 String str=defaultValue.substring(7).trim(); 802 Double d = Caster.toDouble(str,null); 803 if(d!=null){ 804 this.attributeDefaultValue=LitDouble.toExprDouble(d.doubleValue()); 805 return; 806 } 807 808 } 809 else this.attributeDefaultValue=LitString.toExprString(defaultValue); 810 } 811 }