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