001 package railo.runtime.type.scope; 002 003 import java.util.ArrayList; 004 import java.util.Iterator; 005 import java.util.List; 006 007 import railo.runtime.PageContext; 008 import railo.runtime.PageContextImpl; 009 import railo.runtime.config.Config; 010 import railo.runtime.dump.DumpData; 011 import railo.runtime.dump.DumpProperties; 012 import railo.runtime.exp.ExpressionException; 013 import railo.runtime.exp.PageException; 014 import railo.runtime.type.Collection; 015 import railo.runtime.type.KeyImpl; 016 import railo.runtime.type.Query; 017 import railo.runtime.type.Scope; 018 import railo.runtime.type.Struct; 019 import railo.runtime.type.StructImpl; 020 import railo.runtime.type.dt.DateTime; 021 import railo.runtime.type.util.StructSupport; 022 import railo.runtime.util.QueryStack; 023 import railo.runtime.util.QueryStackImpl; 024 025 /** 026 * Undefined Scope 027 */ 028 public final class UndefinedImpl extends StructSupport implements Undefined { 029 030 private static final Collection.Key QUERY = KeyImpl.intern("query"); 031 private Collection[] scopes; 032 private QueryStackImpl qryStack=new QueryStackImpl(); 033 private Scope variable; 034 private boolean allowImplicidQueryCall; 035 private boolean checkArguments; 036 037 038 039 private boolean localAlways; 040 private short type; 041 private boolean isInit; 042 private Scope local; 043 private ArgumentPro argument; 044 private PageContextImpl pc; 045 046 /** 047 * constructor of the class 048 * @param pageContextImpl 049 * @param type type of the undefined scope (ServletConfigImpl.SCOPE_STRICT;ServletConfigImpl.SCOPE_SMALL;ServletConfigImpl.SCOPE_STANDART) 050 */ 051 public UndefinedImpl(PageContextImpl pc, short type) { 052 this.type=type; 053 this.pc=pc; 054 } 055 056 057 /** 058 * @see railo.runtime.type.scope.Undefined#localScope() 059 */ 060 public Scope localScope() { 061 return local; 062 } 063 064 065 // FUTURE add to interface 066 public ArgumentPro argumentsScope() { 067 // TODO Auto-generated method stub 068 return argument; 069 } 070 071 // FUTURE add to interface 072 public Variables variablesScope() { 073 return (Variables) variable; 074 } 075 076 /* 077 * @see railo.runtime.type.scope.Undefined#check Arguments(boolean) 078 * / 079 public boolean check Arguments(boolean b) { 080 boolean old=this.check Arguments; 081 this.check Arguments=b; 082 return old; 083 }*/ 084 085 /** 086 * @see railo.runtime.type.scope.Undefined#setMode(int) 087 */ 088 public int setMode(int mode) { 089 int m=Undefined.MODE_NO_LOCAL_AND_ARGUMENTS; 090 if(checkArguments) { 091 if(localAlways)m=Undefined.MODE_LOCAL_OR_ARGUMENTS_ALWAYS; 092 else m=Undefined.MODE_LOCAL_OR_ARGUMENTS_ONLY_WHEN_EXISTS; 093 } 094 095 checkArguments=mode!=Undefined.MODE_NO_LOCAL_AND_ARGUMENTS; 096 localAlways=mode==Undefined.MODE_LOCAL_OR_ARGUMENTS_ALWAYS; 097 return m; 098 } 099 100 101 /** 102 * @see railo.runtime.type.scope.Undefined#setFunctionScopes(railo.runtime.type.Scope, railo.runtime.type.Scope) 103 */ 104 public void setFunctionScopes(Scope local, Scope argument) {// FUTURE setFunctionScopes(Local local,Argument argument) 105 this.local=local; 106 this.argument=(ArgumentPro) argument; 107 } 108 109 /** 110 * @see railo.runtime.type.scope.Undefined#getCollectionStack() 111 */ 112 public QueryStack getCollectionStack() { 113 return getQueryStack(); 114 } 115 116 /** 117 * @see railo.runtime.type.scope.Undefined#getQueryStack() 118 */ 119 public QueryStack getQueryStack() { 120 return qryStack; 121 } 122 123 /** 124 * @see railo.runtime.type.scope.Undefined#setCollectionStack(railo.runtime.util.QueryStack) 125 */ 126 public void setCollectionStack(QueryStack collStack) { 127 setQueryStack(collStack); 128 } 129 130 /** 131 * @see railo.runtime.type.scope.Undefined#setQueryStack(railo.runtime.util.QueryStack) 132 */ 133 public void setQueryStack(QueryStack qryStack) { 134 this.qryStack=(QueryStackImpl) qryStack; 135 } 136 137 /** 138 * @see railo.runtime.type.scope.Undefined#addCollection(railo.runtime.type.Query) 139 */ 140 public void addCollection(Query coll) { 141 addQuery(coll); 142 } 143 144 /** 145 * @see railo.runtime.type.scope.Undefined#addQuery(railo.runtime.type.Query) 146 */ 147 public void addQuery(Query qry) { 148 if(allowImplicidQueryCall) 149 qryStack.addQuery(qry); 150 } 151 152 /** 153 * @see railo.runtime.type.scope.Undefined#removeCollection() 154 */ 155 public void removeCollection() { 156 removeQuery(); 157 } 158 159 /** 160 * @see railo.runtime.type.scope.Undefined#removeQuery() 161 */ 162 public void removeQuery() { 163 if(allowImplicidQueryCall) 164 qryStack.removeQuery(); 165 } 166 167 /** 168 * @see railo.runtime.type.Collection#size() 169 */ 170 public int size() { 171 return variable.size(); 172 } 173 174 /** 175 * @see railo.runtime.type.Collection#keysAsString() 176 */ 177 public String[] keysAsString() { 178 return variable.keysAsString(); 179 } 180 181 /** 182 * @see railo.runtime.type.Collection#keys() 183 */ 184 public Collection.Key[] keys() { 185 return variable.keys(); 186 } 187 188 /** 189 * @see railo.runtime.type.Collection#remove(railo.runtime.type.Collection.Key) 190 */ 191 public Object remove(Collection.Key key) throws PageException { 192 if(checkArguments && local.containsKey(key)) 193 return local.remove(key); 194 return variable.remove(key); 195 } 196 197 /** 198 * 199 * @see railo.runtime.type.Collection#removeEL(railo.runtime.type.Collection.Key) 200 */ 201 public Object removeEL(Collection.Key key) { 202 if(checkArguments && local.containsKey(key)) 203 return local.removeEL(key); 204 return variable.removeEL(key); 205 } 206 207 /** 208 * @see railo.runtime.type.Collection#clear() 209 */ 210 public void clear() { 211 variable.clear(); 212 } 213 214 public Object get(Collection.Key key) throws PageException { 215 216 Object rtn=null; 217 if(checkArguments) { 218 rtn=local.get(key,null); 219 if(rtn!=null) return rtn; 220 221 rtn=argument.getFunctionArgument(key,null); 222 if(rtn!=null) return rtn; 223 } 224 225 // get data from queries 226 if(allowImplicidQueryCall && !qryStack.isEmpty()) { 227 rtn=qryStack.getDataFromACollection(pc,key); 228 if(rtn!=null) { 229 return rtn; 230 } 231 } 232 233 // variable 234 rtn=variable.get(key,null); 235 if(rtn!=null) { 236 return rtn; 237 } 238 239 // thread scopes 240 if(pc.hasFamily()) { 241 rtn = pc.getThreadScope(key,null); 242 if(rtn!=null) return rtn; 243 } 244 245 // get a scope value 246 for(int i=0;i<scopes.length;i++) { 247 rtn=scopes[i].get(key,null); 248 if(rtn!=null) { 249 return rtn; 250 } 251 } 252 throw new ExpressionException("variable ["+key.getString()+"] doesn't exist"); 253 } 254 255 /** 256 * @see railo.runtime.type.scope.Undefined#getCollection(java.lang.String) 257 */ 258 public Object getCollection(String key) throws ExpressionException { 259 Object rtn=null; 260 261 if(checkArguments) { 262 rtn=local.get(key,null); 263 if(rtn!=null) return rtn; 264 rtn=argument.getFunctionArgument(key,null); 265 if(rtn!=null) return rtn; 266 } 267 268 // get data from queries 269 if(allowImplicidQueryCall && !qryStack.isEmpty()) { 270 rtn=qryStack.getColumnFromACollection(key); 271 if(rtn!=null) return rtn; 272 } 273 274 // variable 275 rtn=variable.get(key,null); 276 if(rtn!=null) { 277 return rtn; 278 } 279 280 // thread scopes 281 if(pc.hasFamily()) { 282 rtn = pc.getThreadScope(key,null); 283 if(rtn!=null) return rtn; 284 } 285 286 // get a scope value 287 for(int i=0;i<scopes.length;i++) { 288 rtn=scopes[i].get(key,null); 289 if(rtn!=null) { 290 return rtn; 291 } 292 } 293 throw new ExpressionException("variable ["+key+"] doesn't exist"); 294 } 295 296 public Struct getScope(String key) { 297 Object rtn=null; 298 Struct sct=new StructImpl(Struct.TYPE_LINKED); 299 300 if(checkArguments) { 301 rtn=local.get(key,null); 302 if(rtn!=null) sct.setEL(KeyImpl.LOCAL, rtn); 303 rtn=argument.getFunctionArgument(key,null); 304 if(rtn!=null) sct.setEL(KeyImpl.ARGUMENTS, rtn); 305 } 306 307 // get data from queries 308 if(allowImplicidQueryCall && !qryStack.isEmpty()) { 309 rtn=qryStack.getColumnFromACollection(key); 310 if(rtn!=null) sct.setEL(QUERY, rtn); 311 } 312 313 // variable 314 rtn=variable.get(key,null); 315 if(rtn!=null) { 316 sct.setEL(KeyImpl.VARIABLES, rtn); 317 } 318 319 // thread scopes 320 if(pc.hasFamily()) { 321 rtn = pc.getThreadScope(key,null); 322 if(rtn!=null) sct.setEL(KeyImpl.THREAD, rtn); 323 } 324 325 // get a scope value 326 for(int i=0;i<scopes.length;i++) { 327 rtn=scopes[i].get(key,null); 328 if(rtn!=null) { 329 sct.setEL(((Scope)scopes[i]).getTypeAsString(), rtn); 330 } 331 } 332 return sct; 333 } 334 335 /** 336 * return a list of String with the scope names 337 * @param key 338 * @return 339 */ 340 public List getScopeNames() { 341 List scopeNames=new ArrayList(); 342 343 if(checkArguments) { 344 scopeNames.add("local"); 345 scopeNames.add("arguments"); 346 } 347 scopeNames.add("variables"); 348 349 // thread scopes 350 if(pc.hasFamily()) { 351 String[] names = pc.getThreadScopeNames(); 352 for(int i=0;i<names.length;i++)scopeNames.add(i,names[i]); 353 } 354 355 for(int i=0;i<scopes.length;i++) { 356 357 scopeNames.add(((Scope)scopes[i]).getTypeAsString()); 358 } 359 return scopeNames; 360 361 362 363 } 364 365 public Object getCollection(Key key) throws PageException { 366 Object rtn=null; 367 368 if(checkArguments) { 369 rtn=local.get(key,null); 370 if(rtn!=null) return rtn; 371 rtn=argument.getFunctionArgument(key,null); 372 if(rtn!=null) return rtn; 373 } 374 375 // get data from queries 376 if(allowImplicidQueryCall && !qryStack.isEmpty()) { 377 rtn=qryStack.getColumnFromACollection(key); 378 if(rtn!=null) return rtn; 379 } 380 381 // variable 382 rtn=variable.get(key,null); 383 if(rtn!=null) { 384 return rtn; 385 } 386 387 // thread scopes 388 if(pc.hasFamily()) { 389 rtn = pc.getThreadScope(key,null); 390 if(rtn!=null) return rtn; 391 } 392 393 // get a scope value 394 for(int i=0;i<scopes.length;i++) { 395 rtn=scopes[i].get(key,null); 396 if(rtn!=null) { 397 return rtn; 398 } 399 } 400 throw new ExpressionException("variable ["+key.getString()+"] doesn't exist"); 401 } 402 403 public Object get(Collection.Key key, Object defaultValue) { 404 Object rtn=null; 405 406 if(checkArguments) { 407 rtn=local.get(key,null); 408 if(rtn!=null) return rtn; 409 rtn=argument.getFunctionArgument(key,null); 410 if(rtn!=null) return rtn; 411 } 412 413 // get data from queries 414 if(allowImplicidQueryCall && !qryStack.isEmpty()) { 415 rtn=qryStack.getDataFromACollection(key); 416 if(rtn!=null) return rtn; 417 } 418 419 // variable 420 rtn=variable.get(key,null); 421 if(rtn!=null) { 422 return rtn; 423 } 424 425 // thread scopes 426 if(pc.hasFamily()) { 427 rtn = pc.getThreadScope(key,null); 428 if(rtn!=null) return rtn; 429 } 430 431 // get a scope value 432 for(int i=0;i<scopes.length;i++) { 433 rtn=scopes[i].get(key,null); 434 if(rtn!=null) { 435 return rtn; 436 } 437 } 438 return defaultValue; 439 } 440 441 442 /** 443 * @see railo.runtime.type.scope.Undefined#getCascading(java.lang.String) 444 */ 445 public Object getCascading(String strKey) { 446 Object rtn=null; 447 Key key = KeyImpl.init(strKey); 448 // get a scope value 449 for(int i=0;i<scopes.length;i++) { 450 rtn=scopes[i].get(key,null); 451 if(rtn!=null) { 452 return rtn; 453 } 454 } 455 return null; 456 } 457 458 459 /** 460 * 461 * @see railo.runtime.type.scope.Undefined#getCascading(railo.runtime.type.Collection.Key) 462 */ 463 public Object getCascading(Collection.Key key) { 464 Object rtn=null; 465 466 // get a scope value 467 for(int i=0;i<scopes.length;i++) { 468 rtn=scopes[i].get(key,null); 469 if(rtn!=null) { 470 return rtn; 471 } 472 } 473 return null; 474 } 475 476 /** 477 * @see railo.runtime.type.Collection#setEL(railo.runtime.type.Collection.Key, java.lang.Object) 478 */ 479 public Object setEL(Collection.Key key, Object value) { 480 if(checkArguments) { 481 if(localAlways || local.containsKey(key)) return local.setEL(key,value); 482 if(argument.containsFunctionArgumentKey(key)) return argument.setEL(key,value); 483 } 484 485 return variable.setEL(key,value); 486 } 487 488 /** 489 * 490 * @see railo.runtime.type.Collection#set(railo.runtime.type.Collection.Key, java.lang.Object) 491 */ 492 public Object set(Collection.Key key, Object value) throws PageException { 493 if(checkArguments) { 494 if(localAlways || local.containsKey(key)) return local.set(key,value); 495 if(argument.containsFunctionArgumentKey(key)) return argument.set(key,value); 496 497 } 498 return variable.set(key,value); 499 } 500 501 /** 502 * @see railo.runtime.dump.Dumpable#toDumpData(railo.runtime.PageContext, int) 503 */ 504 public DumpData toDumpData(PageContext pageContext, int maxlevel, DumpProperties dp) { 505 return variable.toDumpData(pageContext, maxlevel,dp); 506 } 507 508 /** 509 * @see railo.runtime.type.Collection#keyIterator() 510 */ 511 public Iterator keyIterator() { 512 return variable.keyIterator(); 513 } 514 515 /** 516 * @see railo.runtime.type.Scope#isInitalized() 517 */ 518 public boolean isInitalized() { 519 return isInit; 520 } 521 522 /** 523 * @see railo.runtime.type.Scope#initialize(railo.runtime.PageContext) 524 */ 525 public void initialize(PageContext pc) { 526 if(isInitalized()) return; 527 isInit=true; 528 variable=pc.variablesScope(); 529 argument=(ArgumentPro) pc.argumentsScope(); 530 local=pc.localScope(); 531 allowImplicidQueryCall=pc.getConfig().allowImplicidQueryCall(); 532 type=pc.getConfig().getScopeCascadingType(); 533 534 // Strict 535 if(type==Config.SCOPE_STRICT) { 536 //print.ln("strict"); 537 scopes=new Collection[] {}; 538 } 539 // small 540 else if(type==Config.SCOPE_SMALL) { 541 //print.ln("small"); 542 if(pc.getConfig().mergeFormAndURL()) { 543 scopes=new Collection[] { 544 pc.formScope() 545 }; 546 } 547 else { 548 scopes=new Collection[] { 549 pc.urlScope(), 550 pc.formScope() 551 }; 552 } 553 } 554 // standard 555 else { 556 reinitialize((PageContextImpl) pc); 557 } 558 559 560 } 561 562 public void reinitialize(PageContextImpl pc) { 563 if(type!=Config.SCOPE_STANDARD) return; 564 Client cs = pc.clientScopeEL(); 565 // print.ln("standard"); 566 if(pc.getConfig().mergeFormAndURL()) { 567 scopes=new Collection[cs==null?3:4]; 568 scopes[0]=pc.cgiScope(); 569 scopes[1]=pc.formScope(); 570 scopes[2]=pc.cookieScope(); 571 if(cs!=null)scopes[3]=cs; 572 } 573 else { 574 scopes=new Collection[cs==null?4:5]; 575 scopes[0]=pc.cgiScope(); 576 scopes[1]=pc.urlScope(); 577 scopes[2]=pc.formScope(); 578 scopes[3]=pc.cookieScope(); 579 if(cs!=null)scopes[4]=cs; 580 } 581 } 582 583 584 /** 585 * @see railo.runtime.type.Scope#release() 586 */ 587 public void release() { 588 isInit=false; 589 argument=null; 590 local=null; 591 variable=null; 592 scopes=null; 593 checkArguments=false; 594 localAlways=false; 595 if(allowImplicidQueryCall)qryStack.clear(); 596 597 598 //threads=null; 599 //hasThreads=false; 600 } 601 602 /** 603 * @see railo.runtime.type.Collection#duplicate(boolean) 604 */ 605 public Collection duplicate(boolean deepCopy) { 606 UndefinedImpl dupl = new UndefinedImpl(pc, type); 607 dupl.allowImplicidQueryCall=allowImplicidQueryCall; 608 dupl.checkArguments=checkArguments; 609 dupl.argument=deepCopy?(ArgumentPro)argument.duplicate(deepCopy):argument; 610 dupl.isInit=isInit; 611 dupl.local=deepCopy?(Scope)local.duplicate(deepCopy):local; 612 dupl.localAlways=localAlways; 613 dupl.qryStack= (deepCopy?(QueryStackImpl)qryStack.duplicate(deepCopy):qryStack); 614 615 dupl.variable=deepCopy?(Scope)variable.duplicate(deepCopy):variable; 616 617 // scopes 618 if(deepCopy) { 619 dupl.scopes=new Collection[scopes.length]; 620 for(int i=0;i<scopes.length;i++) { 621 dupl.scopes[i]=scopes[i].duplicate(deepCopy); 622 } 623 } 624 else dupl.scopes=scopes; 625 626 return dupl; 627 } 628 629 630 /** 631 * 632 * @see railo.runtime.type.Collection#containsKey(railo.runtime.type.Collection.Key) 633 */ 634 public boolean containsKey(Key key) { 635 return get(key,null)!=null; 636 } 637 638 /** 639 * @see railo.runtime.op.Castable#castToString() 640 */ 641 public String castToString() throws ExpressionException { 642 throw new ExpressionException("Can't cast Complex Object Type Struct to String", 643 "Use Build-In-Function \"serialize(Struct):String\" to create a String from Struct"); 644 } 645 646 /** 647 * @see railo.runtime.type.util.StructSupport#castToString(java.lang.String) 648 */ 649 public String castToString(String defaultValue) { 650 return defaultValue; 651 } 652 653 /** 654 * @see railo.runtime.op.Castable#castToBooleanValue() 655 */ 656 public boolean castToBooleanValue() throws ExpressionException { 657 throw new ExpressionException("Can't cast Complex Object Type Struct to a boolean value"); 658 } 659 660 /** 661 * @see railo.runtime.op.Castable#castToBoolean(java.lang.Boolean) 662 */ 663 public Boolean castToBoolean(Boolean defaultValue) { 664 return defaultValue; 665 } 666 667 668 /** 669 * @see railo.runtime.op.Castable#castToDoubleValue() 670 */ 671 public double castToDoubleValue() throws ExpressionException { 672 throw new ExpressionException("Can't cast Complex Object Type Struct to a number value"); 673 } 674 675 /** 676 * @see railo.runtime.op.Castable#castToDoubleValue(double) 677 */ 678 public double castToDoubleValue(double defaultValue) { 679 return defaultValue; 680 } 681 682 683 /** 684 * @see railo.runtime.op.Castable#castToDateTime() 685 */ 686 public DateTime castToDateTime() throws ExpressionException { 687 throw new ExpressionException("Can't cast Complex Object Type Struct to a Date"); 688 } 689 690 /** 691 * @see railo.runtime.op.Castable#castToDateTime(railo.runtime.type.dt.DateTime) 692 */ 693 public DateTime castToDateTime(DateTime defaultValue) { 694 return defaultValue; 695 } 696 697 /** 698 * @see railo.runtime.op.Castable#compare(boolean) 699 */ 700 public int compareTo(boolean b) throws ExpressionException { 701 throw new ExpressionException("can't compare Complex Object Type Struct with a boolean value"); 702 } 703 704 /** 705 * @see railo.runtime.op.Castable#compareTo(railo.runtime.type.dt.DateTime) 706 */ 707 public int compareTo(DateTime dt) throws PageException { 708 throw new ExpressionException("can't compare Complex Object Type Struct with a DateTime Object"); 709 } 710 711 /** 712 * @see railo.runtime.op.Castable#compareTo(double) 713 */ 714 public int compareTo(double d) throws PageException { 715 throw new ExpressionException("can't compare Complex Object Type Struct with a numeric value"); 716 } 717 718 /** 719 * @see railo.runtime.op.Castable#compareTo(java.lang.String) 720 */ 721 public int compareTo(String str) throws PageException { 722 throw new ExpressionException("can't compare Complex Object Type Struct with a String"); 723 } 724 725 /** 726 * @see railo.runtime.type.scope.Undefined#setVariableScope(railo.runtime.type.Scope) 727 */ 728 public void setVariableScope(Scope scope) { 729 variable=scope; 730 } 731 732 /** 733 * @see railo.runtime.type.Scope#getType() 734 */ 735 public int getType() { 736 return SCOPE_UNDEFINED; 737 } 738 739 /** 740 * @see railo.runtime.type.Scope#getTypeAsString() 741 */ 742 public String getTypeAsString() { 743 return "undefined"; 744 } 745 746 747 /** 748 * @return the allowImplicidQueryCall 749 */ 750 public boolean isAllowImplicidQueryCall() { 751 return allowImplicidQueryCall; 752 } 753 754 755 /** 756 * @param allowImplicidQueryCall the allowImplicidQueryCall to set 757 */ 758 public boolean setAllowImplicidQueryCall(boolean allowImplicidQueryCall) { 759 boolean old=this.allowImplicidQueryCall; 760 this.allowImplicidQueryCall = allowImplicidQueryCall; 761 return old; 762 } 763 764 /** 765 * @return the checkArguments 766 */ 767 public boolean getCheckArguments() { 768 return checkArguments; 769 } 770 771 772 }