001 package railo.runtime.type; 002 003 import java.io.Externalizable; 004 import java.io.IOException; 005 import java.io.ObjectInput; 006 import java.io.ObjectOutput; 007 import java.util.Iterator; 008 import java.util.Map; 009 import java.util.Map.Entry; 010 011 import javax.servlet.jsp.tagext.BodyContent; 012 013 import railo.commons.lang.CFTypes; 014 import railo.commons.lang.SizeOf; 015 import railo.commons.lang.StringUtil; 016 import railo.runtime.Component; 017 import railo.runtime.ComponentImpl; 018 import railo.runtime.Page; 019 import railo.runtime.PageContext; 020 import railo.runtime.PageContextImpl; 021 import railo.runtime.PageSource; 022 import railo.runtime.component.MemberSupport; 023 import railo.runtime.dump.DumpData; 024 import railo.runtime.dump.DumpProperties; 025 import railo.runtime.dump.DumpRow; 026 import railo.runtime.dump.DumpTable; 027 import railo.runtime.dump.DumpTablePro; 028 import railo.runtime.dump.SimpleDumpData; 029 import railo.runtime.exp.DeprecatedException; 030 import railo.runtime.exp.ExpressionException; 031 import railo.runtime.exp.PageException; 032 import railo.runtime.exp.PageRuntimeException; 033 import railo.runtime.exp.UDFCasterException; 034 import railo.runtime.listener.ApplicationContextPro; 035 import railo.runtime.op.Caster; 036 import railo.runtime.op.Decision; 037 import railo.runtime.op.Duplicator; 038 import railo.runtime.type.Collection.Key; 039 import railo.runtime.type.scope.Argument; 040 import railo.runtime.type.scope.ArgumentIntKey; 041 import railo.runtime.type.scope.ArgumentPro; 042 import railo.runtime.type.scope.LocalImpl; 043 import railo.runtime.type.scope.Undefined; 044 import railo.runtime.type.util.ComponentUtil; 045 import railo.runtime.writer.BodyContentUtil; 046 047 /** 048 * defines a abstract class for a User defined Functions 049 */ 050 public class UDFImpl extends MemberSupport implements UDF,Sizeable,Externalizable { 051 052 private static final FunctionArgument[] EMPTY = new FunctionArgument[0]; 053 054 055 056 private ComponentImpl ownerComponent; 057 private UDFProperties properties; 058 059 060 /** 061 * @see railo.runtime.engine.Sizeable#sizeOf() 062 */ 063 public long sizeOf() { 064 return SizeOf.size(properties); 065 } 066 067 068 /** 069 * Constructor of the class 070 * @param page 071 * @param arguments 072 * @param index 073 * @param functionName 074 * @param strReturnType 075 * @param strReturnFormat 076 * @param output 077 * @param async 078 * @param strAccess 079 * @param displayName 080 * @param description 081 * @param hint 082 * @param secureJson 083 * @param verifyClient 084 * @param meta 085 * @throws ExpressionException 086 * @deprecated use instead <code>UDFImpl(UDFProperties properties)</code> 087 */ 088 public UDFImpl( 089 Page page, 090 FunctionArgument[] arguments, 091 int index, 092 String functionName, 093 String strReturnType, 094 String strReturnFormat, 095 boolean output, 096 boolean async, 097 String strAccess, 098 String displayName, 099 String description, 100 String hint, 101 Boolean secureJson, 102 Boolean verifyClient, 103 StructImpl meta) throws ExpressionException { 104 super(ComponentUtil.toIntAccess(strAccess)); 105 properties=new UDFProperties(page, 106 arguments, 107 index, 108 functionName, 109 strReturnType, 110 strReturnFormat, 111 output, 112 async, 113 getAccess(), 114 displayName, 115 description, 116 hint, 117 secureJson, 118 verifyClient, 119 meta); 120 121 } 122 123 /** 124 * Constructor of the class 125 * @param page 126 * @param arguments 127 * @param index 128 * @param functionName 129 * @param returnType 130 * @param strReturnFormat 131 * @param output 132 * @param async 133 * @param strAccess 134 * @param displayName 135 * @param description 136 * @param hint 137 * @param secureJson 138 * @param verifyClient 139 * @param meta 140 * @throws ExpressionException 141 * @deprecated use instead <code>UDFImpl(UDFProperties properties)</code> 142 */ 143 public UDFImpl( 144 Page page, 145 FunctionArgument[] arguments, 146 int index, 147 String functionName, 148 short returnType, 149 String strReturnFormat, 150 boolean output, 151 boolean async, 152 String strAccess, 153 String displayName, 154 String description, 155 String hint, 156 Boolean secureJson, 157 Boolean verifyClient, 158 StructImpl meta) throws ExpressionException { 159 super(ComponentUtil.toIntAccess(strAccess)); 160 properties=new UDFProperties( 161 page, 162 arguments, 163 index, 164 functionName, 165 returnType, 166 strReturnFormat, 167 output, 168 async, 169 getAccess(), 170 displayName, 171 description, 172 hint, 173 secureJson, 174 verifyClient, 175 meta); 176 //ownerComponent=null; 177 } 178 179 /** 180 * DO NOT USE THIS CONSTRUCTOR! 181 * this constructor is only for deserialize process 182 */ 183 public UDFImpl(){ 184 super(0); 185 } 186 187 public UDFImpl(UDFProperties properties) { 188 super(properties.getAccess()); 189 this.properties=properties; 190 } 191 192 public UDF duplicate(ComponentImpl c) { 193 UDFImpl udf = new UDFImpl(properties); 194 udf.ownerComponent=c; 195 udf.setAccess(getAccess()); 196 return udf; 197 } 198 199 public UDF duplicate(boolean deepCopy) { 200 return duplicate(ownerComponent); 201 } 202 203 public UDF duplicate() { 204 return duplicate(ownerComponent); 205 } 206 207 /** 208 * @throws Throwable 209 * @see railo.runtime.type.UDF#implementation(railo.runtime.PageContext) 210 */ 211 public Object implementation(PageContext pageContext) throws Throwable { 212 213 214 215 return ComponentUtil.getPage(pageContext, properties.pageSource).udfCall(pageContext,this,properties.index); 216 } 217 218 private final Object castToAndClone(PageContext pc,FunctionArgument arg,Object value, int index) throws PageException { 219 //if(value instanceof Array)print.out(count++); 220 if(Decision.isCastableTo(arg.getType(),arg.getTypeAsString(),value)) 221 return arg.isPassByReference()?value:Duplicator.duplicate(value,false); 222 throw new UDFCasterException(this,arg,value,index); 223 //REALCAST return Caster.castTo(pc,arg.getType(),arg.getTypeAsString(),value); 224 } 225 private final Object castTo(FunctionArgument arg,Object value, int index) throws PageException { 226 if(Decision.isCastableTo(arg.getType(),arg.getTypeAsString(),value)) return value; 227 throw new UDFCasterException(this,arg,value,index); 228 } 229 230 private void defineArguments(PageContext pc,FunctionArgument[] funcArgs, Object[] args,ArgumentPro newArgs) throws PageException { 231 // define argument scope 232 for(int i=0;i<funcArgs.length;i++) { 233 // argument defined 234 if(args.length>i) { 235 newArgs.setEL(funcArgs[i].getName(),castToAndClone(pc,funcArgs[i], args[i],i+1)); 236 } 237 // argument not defined 238 else { 239 Object d=getDefaultValue(pc,i); 240 if(d==null) { 241 if(funcArgs[i].isRequired()) { 242 throw new ExpressionException("The parameter "+funcArgs[i].getName()+" to function "+getFunctionName()+" is required but was not passed in."); 243 } 244 newArgs.setEL(funcArgs[i].getName(),ArgumentPro.NULL); 245 } 246 else { 247 newArgs.setEL(funcArgs[i].getName(),castTo(funcArgs[i],d,i+1)); 248 } 249 } 250 } 251 for(int i=funcArgs.length;i<args.length;i++) { 252 newArgs.setEL(ArgumentIntKey.init(i+1),args[i]); 253 } 254 } 255 256 257 private void defineArguments(PageContext pageContext, FunctionArgument[] funcArgs, Struct values, ArgumentPro newArgs) throws PageException { 258 // argumentCollection 259 argumentCollection(values,funcArgs); 260 //print.out(values.size()); 261 Object value; 262 Collection.Key name; 263 264 for(int i=0;i<funcArgs.length;i++) { 265 // argument defined 266 name=funcArgs[i].getName(); 267 value=values.removeEL(name); 268 if(value!=null) { 269 newArgs.set(name,castToAndClone(pageContext,funcArgs[i], value,i+1)); 270 continue; 271 } 272 else { 273 value=values.removeEL(ArgumentIntKey.init(i+1)); 274 if(value!=null) { 275 newArgs.set(name,castToAndClone(pageContext,funcArgs[i], value,i+1)); 276 continue; 277 } 278 } 279 280 // default argument or exception 281 Object defaultValue=getDefaultValue(pageContext,i);//funcArgs[i].getDefaultValue(); 282 if(defaultValue==null) { 283 if(funcArgs[i].isRequired()) { 284 throw new ExpressionException("The parameter "+funcArgs[i].getName()+" to function "+getFunctionName()+" is required but was not passed in."); 285 } 286 newArgs.set(name,ArgumentPro.NULL); 287 } 288 else newArgs.set(name,castTo(funcArgs[i],defaultValue,i+1)); 289 } 290 291 292 Collection.Key[] arr=values.keys(); 293 for(int i=0;i<arr.length;i++) { 294 newArgs.set(arr[i],values.get(arr[i],null)); 295 } 296 } 297 298 299 public static void argumentCollection(Struct values) { 300 argumentCollection(values,EMPTY); 301 } 302 303 public static void argumentCollection(Struct values, FunctionArgument[] funcArgs) { 304 Object value=values.removeEL(KeyImpl.ARGUMENT_COLLECTION); 305 if(value !=null) { 306 value=Caster.unwrap(value,value); 307 308 if(value instanceof Argument) { 309 Argument argColl=(Argument) value; 310 Collection.Key[] keys = argColl.keys(); 311 for(int i=0;i<keys.length;i++) { 312 if(funcArgs.length>i && keys[i] instanceof ArgumentIntKey) { 313 if(!values.containsKey(funcArgs[i].getName())) 314 values.setEL(funcArgs[i].getName(),argColl.get(keys[i],ArgumentPro.NULL)); 315 else 316 values.setEL(keys[i],argColl.get(keys[i],ArgumentPro.NULL)); 317 } 318 else if(!values.containsKey(keys[i])){ 319 values.setEL(keys[i],argColl.get(keys[i],ArgumentPro.NULL)); 320 } 321 } 322 } 323 else if(value instanceof Collection) { 324 Collection argColl=(Collection) value; 325 Collection.Key[] keys = argColl.keys(); 326 for(int i=0;i<keys.length;i++) { 327 if(!values.containsKey(keys[i])){ 328 values.setEL(keys[i],argColl.get(keys[i],ArgumentPro.NULL)); 329 } 330 } 331 } 332 else if(value instanceof Map) { 333 Map map=(Map) value; 334 Iterator it = map.entrySet().iterator(); 335 Map.Entry entry; 336 Key key; 337 while(it.hasNext()) { 338 entry=(Entry) it.next(); 339 key = toKey(entry.getKey()); 340 if(!values.containsKey(key)){ 341 values.setEL(key,entry.getValue()); 342 } 343 } 344 } 345 else if(value instanceof java.util.List) { 346 java.util.List list=(java.util.List) value; 347 Iterator it = list.iterator(); 348 Object v; 349 int index=0; 350 Key k; 351 while(it.hasNext()) { 352 v= it.next(); 353 k=ArgumentIntKey.init(++index); 354 if(!values.containsKey(k)){ 355 values.setEL(k,v); 356 } 357 } 358 } 359 else { 360 values.setEL(KeyImpl.ARGUMENT_COLLECTION,value); 361 } 362 } 363 } 364 365 public static Collection.Key toKey(Object obj) { 366 if(obj==null) return null; 367 if(obj instanceof Collection.Key) return (Collection.Key) obj; 368 String str = Caster.toString(obj,null); 369 if(str==null) return KeyImpl.init(obj.toString()); 370 return KeyImpl.init(str); 371 } 372 373 /** 374 * @see railo.runtime.type.UDF#callWithNamedValues(railo.runtime.PageContext, railo.runtime.type.Struct, boolean) 375 */ 376 public Object callWithNamedValues(PageContext pc, Struct values,boolean doIncludePath) throws PageException { 377 return _call(pc, null, values, doIncludePath); 378 } 379 380 /** 381 * @see railo.runtime.type.UDF#call(railo.runtime.PageContext, java.lang.Object[], boolean) 382 */ 383 public Object call(PageContext pc, Object[] args, boolean doIncludePath) throws PageException { 384 return _call(pc, args,null, doIncludePath); 385 } 386 // private static int count=0; 387 private Object _call(PageContext pc, Object[] args, Struct values,boolean doIncludePath) throws PageException { 388 //print.out(count++); 389 PageContextImpl pci=(PageContextImpl) pc; 390 ArgumentPro newArgs=(ArgumentPro) pci.getScopeFactory().getArgumentInstance();// FUTURE 391 newArgs.setFunctionArgumentNames(properties.argumentsSet); 392 LocalImpl newLocal=pci.getScopeFactory().getLocalInstance(); 393 394 Undefined undefined=pc.undefinedScope(); 395 Argument oldArgs=pc.argumentsScope(); 396 Scope oldLocal=pc.localScope(); 397 398 pci.setFunctionScopes(newLocal,newArgs); 399 int oldCheckArgs=undefined.setMode(((ApplicationContextPro)pc.getApplicationContext()).getLocalMode()); 400 PageSource psInc=null; 401 try { 402 PageSource ps = getPageSource(); 403 if(doIncludePath)psInc = ps; 404 //if(!ps.getDisplayPath().endsWith("Dump.cfc"))print.e(getPageSource().getDisplayPath()); 405 if(doIncludePath && getOwnerComponent()!=null) { 406 //if(!ps.getDisplayPath().endsWith("Dump.cfc"))print.ds(ps.getDisplayPath()); 407 psInc=ComponentUtil.getPageSource(getOwnerComponent()); 408 if(psInc==pci.getCurrentTemplatePageSource()) { 409 psInc=null; 410 } 411 412 } 413 414 415 416 417 pci.addPageSource(ps,psInc); 418 ////////////////////////////////////////// 419 BodyContent bc = (getOutput()?null:pci.pushBody()); 420 //boolean isC=ownerComponent!=null; 421 422 UDF parent=null; 423 if(ownerComponent!=null) { 424 parent=pci.getActiveUDF(); 425 pci.setActiveUDF(this); 426 } 427 Object returnValue = null; 428 429 try { 430 431 if(args!=null) defineArguments(pc,getFunctionArguments(),args,newArgs); 432 else defineArguments(pc,getFunctionArguments(),values,newArgs); 433 434 returnValue=implementation(pci); 435 if(ownerComponent!=null)pci.setActiveUDF(parent); 436 } 437 catch(Throwable t) { 438 if(ownerComponent!=null)pci.setActiveUDF(parent); 439 BodyContentUtil.flushAndPop(pc,bc); 440 throw Caster.toPageException(t); 441 } 442 BodyContentUtil.clearAndPop(pc,bc); 443 //pc.popBody(); 444 445 446 447 448 if(properties.returnType==CFTypes.TYPE_ANY) return returnValue; 449 else if(Decision.isCastableTo(properties.strReturnType,returnValue,false)) return returnValue; 450 else throw new UDFCasterException(this,properties.strReturnType,returnValue); 451 //REALCAST return Caster.castTo(pageContext,returnType,returnValue,false); 452 ////////////////////////////////////////// 453 454 } 455 finally { 456 pc.removeLastPageSource(psInc!=null); 457 pci.setFunctionScopes(oldLocal,oldArgs); 458 undefined.setMode(oldCheckArgs); 459 pci.getScopeFactory().recycle(newArgs); 460 pci.getScopeFactory().recycle(newLocal); 461 } 462 } 463 464 /** 465 * @see railo.runtime.dump.Dumpable#toDumpData(railo.runtime.PageContext, int) 466 */ 467 468 public DumpData toDumpData(PageContext pageContext, int maxlevel, DumpProperties dp) { 469 return toDumpData(pageContext, maxlevel, dp,this); 470 } 471 public static DumpData toDumpData(PageContext pageContext, int maxlevel, DumpProperties dp,UDF udf) { 472 473 if(!dp.getShowUDFs()) 474 return new SimpleDumpData("<UDF>"); 475 476 // arguments 477 FunctionArgument[] args = udf.getFunctionArguments(); 478 479 DumpTable atts = new DumpTablePro("udf","#9999cc","#ccccff","#000000"); 480 481 atts.appendRow(new DumpRow(63,new DumpData[]{new SimpleDumpData("label"),new SimpleDumpData("name"),new SimpleDumpData("required"),new SimpleDumpData("type"),new SimpleDumpData("default"),new SimpleDumpData("hint")})); 482 for(int i=0;i<args.length;i++) { 483 FunctionArgument arg=args[i]; 484 DumpData def; 485 try { 486 Object oa=null; 487 try { 488 oa = udf.getDefaultValue(pageContext,i); 489 } catch (PageException e1) { 490 } 491 if(oa==null)oa="null"; 492 def=new SimpleDumpData(Caster.toString(oa)); 493 } catch (PageException e) { 494 def=new SimpleDumpData(""); 495 } 496 atts.appendRow(new DumpRow(0,new DumpData[]{ 497 new SimpleDumpData(arg.getDisplayName()), 498 new SimpleDumpData(arg.getName().getString()), 499 new SimpleDumpData(arg.isRequired()), 500 new SimpleDumpData(arg.getTypeAsString()), 501 def, 502 new SimpleDumpData(arg.getHint())})); 503 //atts.setRow(0,arg.getHint()); 504 505 } 506 507 DumpTable func = new DumpTable("#9999cc","#ccccff","#000000"); 508 String f="Function "; 509 try { 510 f=StringUtil.ucFirst(ComponentUtil.toStringAccess(udf.getAccess()).toLowerCase())+" "+f; 511 } 512 catch (ExpressionException e) {} 513 func.setTitle(f+udf.getFunctionName()); 514 if(udf instanceof UDFImpl)func.setComment("source:"+((UDFImpl)udf).getPageSource().getDisplayPath()); 515 516 517 if(!StringUtil.isEmpty(udf.getDescription()))func.setComment(udf.getDescription()); 518 519 520 521 func.appendRow(1,new SimpleDumpData("arguments"),atts); 522 func.appendRow(1,new SimpleDumpData("return type"),new SimpleDumpData(udf.getReturnTypeAsString())); 523 524 boolean hasLabel=!StringUtil.isEmpty(udf.getDisplayName());//displayName!=null && !displayName.equals(""); 525 boolean hasHint=!StringUtil.isEmpty(udf.getHint());//hint!=null && !hint.equals(""); 526 527 if(hasLabel || hasHint) { 528 DumpTable box = new DumpTable("#ffffff","#cccccc","#000000"); 529 box.setTitle(hasLabel?udf.getDisplayName():udf.getFunctionName()); 530 if(hasHint)box.appendRow(0,new SimpleDumpData(udf.getHint())); 531 box.appendRow(0,func); 532 return box; 533 } 534 535 return func; 536 } 537 /** 538 * @see railo.runtime.type.UDF#getDisplayName() 539 */ 540 public String getDisplayName() { 541 return properties.displayName; 542 } 543 /** 544 * @see railo.runtime.type.UDF#getHint() 545 */ 546 public String getHint() { 547 return properties.hint; 548 } 549 /** 550 * @see railo.runtime.type.UDF#getPage() 551 * @deprecated use instead getPageSource() 552 */ 553 public Page getPage() { 554 throw new PageRuntimeException(new DeprecatedException("method getPage():Page is no longer suppoted, use instead getPageSource():PageSource")); 555 //return properties.page; 556 } 557 558 // FUTURE add to interface 559 public PageSource getPageSource() { 560 return properties.pageSource; 561 } 562 563 public Struct getMeta() { 564 return properties.meta; 565 } 566 567 public Struct getMetaData(PageContext pc) throws PageException { 568 return ComponentUtil.getMetaData(pc, properties); 569 //return getMetaData(pc, this); 570 } 571 572 /*public static Struct getMetaData(PageContext pc,UDFImpl udf) throws PageException { 573 StructImpl func=new StructImpl(); 574 575 // TODO func.set("roles", value); 576 // TODO func.set("userMetadata", value); neo unterst゚tzt irgendwelche a 577 // meta data 578 Struct meta = udf.getMeta(); 579 if(meta!=null) StructUtil.copy(meta, func, true); 580 581 582 func.set(KeyImpl.ACCESS,ComponentUtil.toStringAccess(udf.getAccess())); 583 String hint=udf.getHint(); 584 if(!StringUtil.isEmpty(hint))func.set(KeyImpl.HINT,hint); 585 String displayname=udf.getDisplayName(); 586 if(!StringUtil.isEmpty(displayname))func.set(KeyImpl.DISPLAY_NAME,displayname); 587 func.set(KeyImpl.NAME,udf.getFunctionName()); 588 func.set(KeyImpl.OUTPUT,Caster.toBoolean(udf.getOutput())); 589 func.set(KeyImpl.RETURN_TYPE, udf.getReturnTypeAsString()); 590 func.set(KeyImpl.DESCRIPTION, udf.getDescription()); 591 592 func.set(KeyImpl.OWNER, udf.getPageSource().getDisplayPath()); 593 594 595 int format = udf.getReturnFormat(); 596 if(format==UDF.RETURN_FORMAT_WDDX) func.set(KeyImpl.RETURN_FORMAT, "wddx"); 597 else if(format==UDF.RETURN_FORMAT_PLAIN) func.set(KeyImpl.RETURN_FORMAT, "plain"); 598 else if(format==UDF.RETURN_FORMAT_JSON) func.set(KeyImpl.RETURN_FORMAT, "json"); 599 else if(format==UDF.RETURN_FORMAT_SERIALIZE)func.set(KeyImpl.RETURN_FORMAT, "serialize"); 600 601 602 FunctionArgument[] args = udf.getFunctionArguments(); 603 Array params=new ArrayImpl(); 604 //Object defaultValue; 605 Struct m; 606 //Object defaultValue; 607 for(int y=0;y<args.length;y++) { 608 StructImpl param=new StructImpl(); 609 param.set(KeyImpl.NAME,args[y].getName().getString()); 610 param.set(KeyImpl.REQUIRED,Caster.toBoolean(args[y].isRequired())); 611 param.set(KeyImpl.TYPE,args[y].getTypeAsString()); 612 displayname=args[y].getDisplayName(); 613 if(!StringUtil.isEmpty(displayname)) param.set(KeyImpl.DISPLAY_NAME,displayname); 614 615 int defType = args[y].getDefaultType(); 616 if(defType==FunctionArgument.DEFAULT_TYPE_RUNTIME_EXPRESSION){ 617 param.set(KeyImpl.DEFAULT, "[runtime expression]"); 618 } 619 else if(defType==FunctionArgument.DEFAULT_TYPE_LITERAL){ 620 param.set(KeyImpl.DEFAULT, udf.getDefaultValue(pc,y)); 621 } 622 623 hint=args[y].getHint(); 624 if(!StringUtil.isEmpty(hint))param.set(KeyImpl.HINT,hint); 625 // TODO func.set("userMetadata", value); neo unterst゚tzt irgendwelche attr, die dann hier ausgebenen werden blレdsinn 626 627 // meta data 628 m=args[y].getMetaData(); 629 if(m!=null) StructUtil.copy(m, param, true); 630 631 params.append(param); 632 } 633 func.set(KeyImpl.PARAMETERS,params); 634 return func; 635 }*/ 636 637 public Object getValue() { 638 return this; 639 } 640 641 642 /** 643 * @param componentImpl the componentImpl to set 644 * @param injected 645 */ 646 public void setOwnerComponent(ComponentImpl component) { 647 //print.err("setOwnerComponent("+this.hashCode()+"-"+component.hashCode()+"):"+component.getPage().getPageSource().getDisplayPath()); 648 this.ownerComponent = component; 649 } 650 651 /** 652 * @see railo.runtime.type.UDF#getOwnerComponent() 653 // FUTURE deprecated 654 */ 655 public Component getOwnerComponent() { 656 return ownerComponent;//+++ 657 } 658 659 660 public String toString() { 661 StringBuffer sb=new StringBuffer(properties.functionName); 662 sb.append("("); 663 int optCount=0; 664 for(int i=0;i<properties.arguments.length;i++) { 665 if(i>0)sb.append(", "); 666 if(!properties.arguments[i].isRequired()){ 667 sb.append("["); 668 optCount++; 669 } 670 sb.append(properties.arguments[i].getTypeAsString()); 671 sb.append(" "); 672 sb.append(properties.arguments[i].getName()); 673 } 674 for(int i=0;i<optCount;i++){ 675 sb.append("]"); 676 } 677 sb.append(")"); 678 return sb.toString(); 679 } 680 681 /** 682 * @see railo.runtime.type.UDF#getSecureJson() 683 */ 684 public Boolean getSecureJson() { 685 return properties.secureJson; 686 } 687 688 /** 689 * @see railo.runtime.type.UDF#getVerifyClient() 690 */ 691 public Boolean getVerifyClient() { 692 return properties.verifyClient; 693 } 694 695 /*public boolean isInjected() { 696 return injected; 697 }*/ 698 699 public Object clone() { 700 return duplicate(); 701 } 702 703 704 705 /** 706 * @see railo.runtime.type.UDF#getFunctionArguments() 707 */ 708 public FunctionArgument[] getFunctionArguments() { 709 return properties.arguments; 710 } 711 712 /** 713 * @see railo.runtime.type.UDF#getDefaultValue(railo.runtime.PageContext, int) 714 */ 715 public Object getDefaultValue(PageContext pc,int index) throws PageException { 716 return ComponentUtil.getPage(pc,properties.pageSource).udfDefaultValue(pc,properties.index,index); 717 } 718 // public abstract Object getDefaultValue(PageContext pc,int index) throws PageException; 719 720 /** 721 * @see railo.runtime.type.UDF#getFunctionName() 722 */ 723 public String getFunctionName() { 724 return properties.functionName; 725 } 726 727 /** 728 * @see railo.runtime.type.UDF#getOutput() 729 */ 730 public boolean getOutput() { 731 return properties.output; 732 } 733 734 /** 735 * @see railo.runtime.type.UDF#getReturnType() 736 */ 737 public int getReturnType() { 738 return properties.returnType; 739 } 740 741 /** 742 * @see railo.runtime.type.UDF#getReturnTypeAsString() 743 */ 744 public String getReturnTypeAsString() { 745 return properties.strReturnType; 746 } 747 748 /** 749 * @see railo.runtime.type.UDF#getDescription() 750 */ 751 public String getDescription() { 752 return properties.description; 753 } 754 755 /** 756 * @see railo.runtime.type.UDF#getReturnFormat() 757 */ 758 public int getReturnFormat() { 759 return properties.returnFormat; 760 } 761 762 public final String getReturnFormatAsString() { 763 return properties.strReturnFormat; 764 } 765 766 767 public static int toReturnFormat(String returnFormat) throws ExpressionException { 768 if(StringUtil.isEmpty(returnFormat,true)) 769 return UDF.RETURN_FORMAT_WDDX; 770 771 772 returnFormat=returnFormat.trim().toLowerCase(); 773 if("wddx".equals(returnFormat)) return UDF.RETURN_FORMAT_WDDX; 774 else if("json".equals(returnFormat)) return UDF.RETURN_FORMAT_JSON; 775 else if("plain".equals(returnFormat)) return UDF.RETURN_FORMAT_PLAIN; 776 else if("text".equals(returnFormat)) return UDF.RETURN_FORMAT_PLAIN; 777 else if("serialize".equals(returnFormat)) return UDF.RETURN_FORMAT_SERIALIZE; 778 else throw new ExpressionException("invalid returnFormat definition ["+returnFormat+"], valid values are [wddx,plain,json,serialize]"); 779 } 780 781 public static String toReturnFormat(int returnFormat) throws ExpressionException { 782 if(RETURN_FORMAT_WDDX==returnFormat) return "wddx"; 783 else if(RETURN_FORMAT_JSON==returnFormat) return "json"; 784 else if(RETURN_FORMAT_PLAIN==returnFormat) return "plain"; 785 else if(RETURN_FORMAT_SERIALIZE==returnFormat) return "serialize"; 786 else throw new ExpressionException("invalid returnFormat definition, valid values are [wddx,plain,json,serialize]"); 787 } 788 789 790 // FUTURE move to interface 791 public static String toReturnFormat(int returnFormat,String defaultValue) { 792 if(RETURN_FORMAT_WDDX==returnFormat) return "wddx"; 793 else if(RETURN_FORMAT_JSON==returnFormat) return "json"; 794 else if(RETURN_FORMAT_PLAIN==returnFormat) return "plain"; 795 else if(RETURN_FORMAT_SERIALIZE==returnFormat) return "serialize"; 796 else return defaultValue; 797 } 798 799 public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { 800 // access 801 setAccess(in.readInt()); 802 803 // properties 804 properties=(UDFProperties) in.readObject(); 805 } 806 807 808 public void writeExternal(ObjectOutput out) throws IOException { 809 // access 810 out.writeInt(getAccess()); 811 812 // properties 813 out.writeObject(properties); 814 815 816 } 817 818 819 } 820