001 package railo.runtime; 002 003 import java.io.FileNotFoundException; 004 import java.io.IOException; 005 import java.io.InputStream; 006 import java.lang.reflect.Constructor; 007 import java.lang.reflect.InvocationTargetException; 008 009 import railo.print; 010 import railo.commons.io.IOUtil; 011 import railo.commons.io.res.Resource; 012 import railo.commons.io.res.util.ResourceUtil; 013 import railo.commons.lang.SizeOf; 014 import railo.commons.lang.StringUtil; 015 import railo.commons.lang.types.RefBoolean; 016 import railo.commons.lang.types.RefBooleanImpl; 017 import railo.runtime.config.ConfigImpl; 018 import railo.runtime.config.ConfigWeb; 019 import railo.runtime.config.ConfigWebImpl; 020 import railo.runtime.engine.ThreadLocalPageContext; 021 import railo.runtime.engine.ThreadLocalPageSource; 022 import railo.runtime.exp.ExpressionException; 023 import railo.runtime.exp.MissingIncludeException; 024 import railo.runtime.exp.PageException; 025 import railo.runtime.exp.TemplateException; 026 import railo.runtime.functions.system.GetDirectoryFromPath; 027 import railo.runtime.op.Caster; 028 import railo.runtime.type.Sizeable; 029 import railo.runtime.type.util.ArrayUtil; 030 import railo.runtime.type.util.ListUtil; 031 032 /** 033 * represent a cfml file on the runtime system 034 */ 035 public final class PageSourceImpl implements SourceFile, PageSource, Sizeable { 036 037 private static final long serialVersionUID = -7661676586215092539L; 038 //public static final byte LOAD_NONE=1; 039 public static final byte LOAD_ARCHIVE=2; 040 public static final byte LOAD_PHYSICAL=3; 041 042 //private byte load=LOAD_NONE; 043 044 private final MappingImpl mapping; 045 private final String realPath; 046 047 private boolean isOutSide; 048 049 private String className; 050 private String packageName; 051 private String javaName; 052 053 private Resource physcalSource; 054 private Resource archiveSource; 055 private String fileName; 056 private String compName; 057 private Page page; 058 private long lastAccess; 059 private int accessCount=0; 060 //private boolean recompileAlways; 061 //private boolean recompileAfterStartUp; 062 063 private PageSourceImpl() { 064 mapping=null; 065 realPath=null; 066 } 067 068 069 /** 070 * constructor of the class 071 * @param mapping 072 * @param realPath 073 */ 074 PageSourceImpl(MappingImpl mapping,String realPath) { 075 this.mapping=mapping; 076 //recompileAlways=mapping.getConfig().getCompileType()==Config.RECOMPILE_ALWAYS; 077 //recompileAfterStartUp=mapping.getConfig().getCompileType()==Config.RECOMPILE_AFTER_STARTUP || recompileAlways; 078 realPath=realPath.replace('\\','/'); 079 if(realPath.indexOf('/')!=0) { 080 if(realPath.startsWith("../")) { 081 isOutSide=true; 082 } 083 else if(realPath.startsWith("./")) { 084 realPath=realPath.substring(1); 085 } 086 else { 087 realPath="/"+realPath; 088 } 089 } 090 this.realPath=realPath; 091 092 } 093 094 095 096 /** 097 * private constructor of the class 098 * @param mapping 099 * @param realPath 100 * @param isOutSide 101 */ 102 PageSourceImpl(MappingImpl mapping, String realPath, boolean isOutSide) { 103 //recompileAlways=mapping.getConfig().getCompileType()==Config.RECOMPILE_ALWAYS; 104 //recompileAfterStartUp=mapping.getConfig().getCompileType()==Config.RECOMPILE_AFTER_STARTUP || recompileAlways; 105 this.mapping=mapping; 106 this.isOutSide=isOutSide; 107 this.realPath=realPath; 108 109 } 110 111 /** 112 * return page when already loaded, otherwise null 113 * @param pc 114 * @param config 115 * @return 116 * @throws PageException 117 */ 118 public Page getPage() { 119 return page; 120 } 121 122 public PageSource getParent(){ 123 if(realPath.equals("/")) return null; 124 if(StringUtil.endsWith(realPath, '/')) 125 return new PageSourceImpl(mapping, GetDirectoryFromPath.invoke(realPath.substring(0, realPath.length()-1))); 126 return new PageSourceImpl(mapping, GetDirectoryFromPath.invoke(realPath)); 127 } 128 129 130 @Override 131 public Page loadPage(ConfigWeb config) throws PageException { 132 return loadPage(ThreadLocalPageContext.get()); 133 } 134 135 @Override 136 public Page loadPage(ConfigWeb config, Page defaultValue) throws PageException { 137 return loadPage(ThreadLocalPageContext.get(), defaultValue); 138 } 139 140 141 public Page loadPage(PageContext pc, boolean forceReload) throws PageException { 142 if(forceReload) page=null; 143 return loadPage(pc); 144 } 145 146 public Page loadPage(PageContext pc) throws PageException { 147 Page page=this.page; 148 if(mapping.isPhysicalFirst()) { 149 page=loadPhysical(pc,page); 150 if(page==null) page=loadArchive(page); 151 if(page!=null) return page; 152 } 153 else { 154 page=loadArchive(page); 155 if(page==null)page=loadPhysical(pc,page); 156 if(page!=null) return page; 157 } 158 throw new MissingIncludeException(this); 159 160 } 161 162 @Override 163 public Page loadPage(PageContext pc, Page defaultValue) throws PageException { 164 Page page=this.page; 165 if(mapping.isPhysicalFirst()) { 166 page=loadPhysical(pc,page); 167 if(page==null) page=loadArchive(page); 168 if(page!=null) return page; 169 } 170 else { 171 page=loadArchive(page); 172 if(page==null)page=loadPhysical(pc,page); 173 if(page!=null) return page; 174 } 175 return defaultValue; 176 } 177 178 private Page loadArchive(Page page) { 179 if(!mapping.hasArchive()) return null; 180 if(page!=null) return page; 181 182 try { 183 synchronized(this) { 184 Class clazz=mapping.getClassLoaderForArchive().loadClass(getClazz()); 185 this.page=page=newInstance(clazz); 186 page.setPageSource(this); 187 //page.setTimeCreated(System.currentTimeMillis()); 188 page.setLoadType(LOAD_ARCHIVE); 189 ////load=LOAD_ARCHIVE; 190 return page; 191 } 192 } 193 catch (Exception e) { 194 return null; 195 } 196 } 197 198 199 private Page loadPhysical(PageContext pc,Page page) throws PageException { 200 if(!mapping.hasPhysical()) return null; 201 202 ConfigWeb config=pc.getConfig(); 203 PageContextImpl pci=(PageContextImpl) pc; 204 if((mapping.getInspectTemplate()==ConfigImpl.INSPECT_NEVER || pci.isTrusted(page)) && isLoad(LOAD_PHYSICAL)) return page; 205 Resource srcFile = getPhyscalFile(); 206 207 /*{ 208 String dp = getDisplayPath(); 209 String cn = getClassName(); 210 if(dp.endsWith(".cfc") && cn.startsWith("cfc")) { 211 print.ds("->"+dp); 212 print.e("trusted:"+mapping.isTrusted()); 213 print.e(mapping.getVirtual()); 214 print.e("mod:"+srcFile.lastModified()); 215 } 216 }*/ 217 218 219 long srcLastModified = srcFile.lastModified(); 220 if(srcLastModified==0L) return null; 221 222 // Page exists 223 if(page!=null) { 224 //if(page!=null && !recompileAlways) { 225 // java file is newer !mapping.isTrusted() && 226 if(srcLastModified!=page.getSourceLastModified()) { 227 this.page=page=compile(config,mapping.getClassRootDirectory(),Boolean.TRUE); 228 page.setPageSource(this); 229 page.setLoadType(LOAD_PHYSICAL); 230 } 231 232 } 233 // page doesn't exist 234 else { 235 ///synchronized(this) { 236 Resource classRootDir=mapping.getClassRootDirectory(); 237 Resource classFile=classRootDir.getRealResource(getJavaName()+".class"); 238 boolean isNew=false; 239 // new class 240 if(!classFile.exists()) { 241 //if(!classFile.exists() || recompileAfterStartUp) { 242 this.page=page= compile(config,classRootDir,Boolean.FALSE); 243 isNew=true; 244 } 245 // load page 246 else { 247 try { 248 this.page=page=newInstance(mapping.touchPCLCollection().getClass(this)); 249 } catch (Throwable t) {t.printStackTrace(); 250 this.page=page=null; 251 } 252 if(page==null) this.page=page=compile(config,classRootDir,Boolean.TRUE); 253 254 } 255 256 // check if there is a newwer version 257 if(!isNew && srcLastModified!=page.getSourceLastModified()) { 258 isNew=true; 259 this.page=page=compile(config,classRootDir,null); 260 } 261 262 // check version 263 if(!isNew && page.getVersion()!=Info.getFullVersionInfo()) { 264 isNew=true; 265 this.page=page=compile(config,classRootDir,null); 266 } 267 268 page.setPageSource(this); 269 page.setLoadType(LOAD_PHYSICAL); 270 271 } 272 pci.setPageUsed(page); 273 return page; 274 } 275 276 private boolean isLoad(byte load) { 277 return page!=null && load==page.getLoadType(); 278 } 279 280 281 private synchronized Page compile(ConfigWeb config,Resource classRootDir, Boolean resetCL) throws PageException { 282 try { 283 return _compile(config, classRootDir, resetCL); 284 } 285 catch(ClassFormatError e) { 286 String msg=StringUtil.emptyIfNull(e.getMessage()); 287 if(StringUtil.indexOfIgnoreCase(msg, "Invalid method Code length")!=-1) { 288 throw new TemplateException("There is too much code inside the template ["+getDisplayPath()+"], Railo was not able to break it into pieces, move parts of your code to an include or a external component/function",msg); 289 } 290 throw Caster.toPageException(e); 291 } 292 catch(Throwable t) { 293 throw Caster.toPageException(t); 294 } 295 } 296 297 private synchronized Page _compile(ConfigWeb config,Resource classRootDir, Boolean resetCL) throws IOException, SecurityException, IllegalArgumentException, PageException { 298 ConfigWebImpl cwi=(ConfigWebImpl) config; 299 300 301 byte[] barr = cwi.getCompiler(). 302 compile(cwi,this,cwi.getTLDs(),cwi.getFLDs(),classRootDir,getJavaName()); 303 Class<?> clazz = mapping.touchPCLCollection().loadClass(getClazz(), barr,isComponent()); 304 try{ 305 return newInstance(clazz); 306 } 307 catch(Throwable t){ 308 PageException pe = Caster.toPageException(t); 309 pe.setExtendedInfo("failed to load template "+getDisplayPath()); 310 throw pe; 311 } 312 } 313 314 private Page newInstance(Class clazz) throws SecurityException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException { 315 try{ 316 Constructor c = clazz.getConstructor(new Class[]{PageSource.class}); 317 return (Page) c.newInstance(new Object[]{this}); 318 } 319 // this only happens with old code from ra files 320 catch(NoSuchMethodException e){ 321 ThreadLocalPageSource.register(this); 322 try{ 323 return (Page) clazz.newInstance(); 324 } 325 finally { 326 ThreadLocalPageSource.release(); 327 } 328 329 330 } 331 } 332 333 334 /** 335 * return source path as String 336 * @return source path as String 337 */ 338 public String getDisplayPath() { 339 if(!mapping.hasArchive()) { 340 return StringUtil.toString(getPhyscalFile(), null); 341 } 342 else if(isLoad(LOAD_PHYSICAL)) { 343 return StringUtil.toString(getPhyscalFile(), null); 344 } 345 else if(isLoad(LOAD_ARCHIVE)) { 346 return StringUtil.toString(getArchiveSourcePath(), null); 347 } 348 else { 349 boolean pse = physcalExists(); 350 boolean ase = archiveExists(); 351 352 if(mapping.isPhysicalFirst()) { 353 if(pse)return getPhyscalFile().toString(); 354 else if(ase)return getArchiveSourcePath(); 355 return getPhyscalFile().toString(); 356 } 357 if(ase)return getArchiveSourcePath(); 358 else if(pse)return getPhyscalFile().toString(); 359 return getArchiveSourcePath(); 360 } 361 } 362 363 public boolean isComponent() { 364 return ResourceUtil.getExtension(getRealpath(), "").equalsIgnoreCase(mapping.getConfig().getCFCExtension()); 365 } 366 367 /** 368 * return file object, based on physical path and realpath 369 * @return file Object 370 */ 371 private String getArchiveSourcePath() { 372 return "zip://"+mapping.getArchive().getAbsolutePath()+"!"+realPath; 373 } 374 375 /** 376 * return file object, based on physical path and realpath 377 * @return file Object 378 */ 379 public Resource getPhyscalFile() { 380 if(physcalSource==null) { 381 if(!mapping.hasPhysical()) { 382 return null; 383 } 384 physcalSource=ResourceUtil.toExactResource(mapping.getPhysical().getRealResource(realPath)); 385 } 386 return physcalSource; 387 } 388 389 public Resource getArchiveFile() { 390 if(archiveSource==null) { 391 if(!mapping.hasArchive()) return null; 392 String path="zip://"+mapping.getArchive().getAbsolutePath()+"!"+realPath; 393 archiveSource = ThreadLocalPageContext.getConfig().getResource(path); 394 } 395 return archiveSource; 396 } 397 398 399 /** 400 * merge to realpath to one 401 * @param mapping 402 * @param parentRealPath 403 * @param newRealPath 404 * @param isOutSide 405 * @return merged realpath 406 */ 407 private static String mergeRealPathes(Mapping mapping,String parentRealPath, String newRealPath, RefBoolean isOutSide) { 408 parentRealPath=pathRemoveLast(parentRealPath,isOutSide); 409 while(newRealPath.startsWith("../")) { 410 parentRealPath=pathRemoveLast(parentRealPath,isOutSide); 411 newRealPath=newRealPath.substring(3); 412 } 413 414 // check if come back 415 String path=parentRealPath.concat("/").concat(newRealPath); 416 417 if(path.startsWith("../")) { 418 int count=0; 419 do { 420 count++; 421 path=path.substring(3); 422 }while(path.startsWith("../")); 423 424 String strRoot=mapping.getPhysical().getAbsolutePath().replace('\\','/'); 425 if(!StringUtil.endsWith(strRoot,'/')) { 426 strRoot+='/'; 427 } 428 int rootLen=strRoot.length(); 429 String[] arr=ListUtil.toStringArray(ListUtil.listToArray(path,'/'),"");//path.split("/"); 430 int tmpLen; 431 for(int i=count;i>0;i--) { 432 if(arr.length>i) { 433 String tmp='/'+list(arr,0,i); 434 tmpLen=rootLen-tmp.length(); 435 if(strRoot.lastIndexOf(tmp)==tmpLen && tmpLen>=0) { 436 StringBuffer rtn=new StringBuffer(); 437 while(i<count-i) { 438 count--; 439 rtn.append("../"); 440 } 441 isOutSide.setValue(rtn.length()!=0); 442 return (rtn.length()==0?"/":rtn.toString())+list(arr,i,arr.length); 443 } 444 } 445 } 446 } 447 return parentRealPath.concat("/").concat(newRealPath); 448 } 449 450 /** 451 * convert a String array to a string list, but only part of it 452 * @param arr String Array 453 * @param from start from here 454 * @param len how many element 455 * @return String list 456 */ 457 private static String list(String[] arr,int from, int len) { 458 StringBuffer sb=new StringBuffer(); 459 for(int i=from;i<len;i++) { 460 sb.append(arr[i]); 461 if(i+1!=arr.length)sb.append('/'); 462 } 463 return sb.toString(); 464 } 465 466 467 468 /** 469 * remove the last elemtn of a path 470 * @param path path to remove last element from it 471 * @param isOutSide 472 * @return path with removed element 473 */ 474 private static String pathRemoveLast(String path, RefBoolean isOutSide) { 475 if(path.length()==0) { 476 isOutSide.setValue(true); 477 return ".."; 478 } 479 else if(path.endsWith("..")){ 480 isOutSide.setValue(true); 481 return path.concat("/..");//path+"/.."; 482 } 483 return path.substring(0,path.lastIndexOf('/')); 484 } 485 486 @Override 487 public String getRealpath() { 488 return realPath; 489 } 490 @Override 491 public String getFullRealpath() { 492 if(mapping.getVirtual().length()==1 || mapping.ignoreVirtual()) 493 return realPath; 494 return mapping.getVirtual()+realPath; 495 } 496 497 /** 498 * @return returns a variable string based on realpath and return it 499 */ 500 public String getRealPathAsVariableString() { 501 return StringUtil.toIdentityVariableName(realPath); 502 } 503 504 @Override 505 public String getClazz() { 506 if(className==null) createClassAndPackage(); 507 if(packageName.length()>0) return packageName+'.'+className; 508 return className; 509 } 510 511 /** 512 * @return returns the a classname matching to filename (Example: test_cfm) 513 */ 514 public String getClassName() { 515 if(className==null) createClassAndPackage(); 516 return className; 517 } 518 519 @Override 520 public String getFileName() { 521 if(fileName==null) createClassAndPackage(); 522 return fileName; 523 } 524 525 @Override 526 public String getJavaName() { 527 if(javaName==null) createClassAndPackage(); 528 return javaName; 529 } 530 531 /** 532 * @return returns the a package matching to file (Example: railo.web) 533 */ 534 public String getPackageName() { 535 if(packageName==null) createClassAndPackage(); 536 return packageName; 537 } 538 @Override 539 public String getComponentName() { 540 if(compName==null) createComponentName(); 541 return compName; 542 } 543 544 545 private synchronized void createClassAndPackage() { 546 String str=realPath; 547 StringBuffer packageName=new StringBuffer(); 548 StringBuffer javaName=new StringBuffer(); 549 550 String[] arr=ListUtil.toStringArrayEL(ListUtil.listToArrayRemoveEmpty(str,'/')); 551 552 String varName; 553 for(int i=0;i<arr.length;i++) { 554 if(i==(arr.length-1)) { 555 int index=arr[i].lastIndexOf('.'); 556 if(index!=-1){ 557 String ext=arr[i].substring(index+1); 558 varName=StringUtil.toVariableName(arr[i].substring(0,index)+"_"+ext); 559 } 560 else varName=StringUtil.toVariableName(arr[i]); 561 varName=varName+"$cf"; 562 className=varName.toLowerCase(); 563 fileName=arr[i]; 564 } 565 else { 566 varName=StringUtil.toVariableName(arr[i]); 567 if(i!=0) { 568 packageName.append('.'); 569 } 570 packageName.append(varName); 571 } 572 javaName.append('/'); 573 javaName.append(varName); 574 } 575 576 this.packageName=packageName.toString().toLowerCase(); 577 this.javaName=javaName.toString().toLowerCase(); 578 579 580 581 } 582 583 584 585 private synchronized void createComponentName() { 586 Resource res = this.getPhyscalFile(); 587 String str=null; 588 if(res!=null) { 589 590 str=res.getAbsolutePath(); 591 str=str.substring(str.length()-realPath.length()); 592 if(!str.equalsIgnoreCase(realPath)) { 593 str=realPath; 594 } 595 } 596 else str=realPath; 597 598 StringBuffer compName=new StringBuffer(); 599 String[] arr; 600 601 // virtual part 602 if(!mapping.ignoreVirtual()) { 603 arr=ListUtil.toStringArrayEL(ListUtil.listToArrayRemoveEmpty(mapping.getVirtual(),"\\/")); 604 for(int i=0;i<arr.length;i++) { 605 if(compName.length()>0) compName.append('.'); 606 compName.append(arr[i]); 607 } 608 } 609 610 // physical part 611 arr=ListUtil.toStringArrayEL(ListUtil.listToArrayRemoveEmpty(str,'/')); 612 for(int i=0;i<arr.length;i++) { 613 if(compName.length()>0) compName.append('.'); 614 if(i==(arr.length-1)) { 615 compName.append(arr[i].substring(0,arr[i].length()-4)); 616 } 617 else compName.append(arr[i]); 618 } 619 this.compName=compName.toString(); 620 } 621 622 @Override 623 public Mapping getMapping() { 624 return mapping; 625 } 626 627 @Override 628 public synchronized boolean exists() { 629 if(mapping.isPhysicalFirst()) 630 return physcalExists() || archiveExists(); 631 return archiveExists() || physcalExists(); 632 } 633 634 @Override 635 public boolean physcalExists() { 636 return ResourceUtil.exists(getPhyscalFile()); 637 } 638 639 private boolean archiveExists() { 640 if(!mapping.hasArchive())return false; 641 try { 642 String clazz = getClazz(); 643 if(clazz==null) return getArchiveFile().exists(); 644 mapping.getClassLoaderForArchive().loadClass(clazz); 645 return true; 646 } 647 catch(ClassNotFoundException cnfe){ 648 return false; 649 } 650 catch (Exception e) { 651 return getArchiveFile().exists(); 652 } 653 } 654 655 /** 656 * return the inputstream of the source file 657 * @return return the inputstream for the source from ohysical or archive 658 * @throws FileNotFoundException 659 */ 660 private InputStream getSourceAsInputStream() throws IOException { 661 if(!mapping.hasArchive()) return IOUtil.toBufferedInputStream(getPhyscalFile().getInputStream()); 662 else if(isLoad(LOAD_PHYSICAL)) return IOUtil.toBufferedInputStream(getPhyscalFile().getInputStream()); 663 else if(isLoad(LOAD_ARCHIVE)) { 664 StringBuffer name=new StringBuffer(getPackageName().replace('.','/')); 665 if(name.length()>0)name.append("/"); 666 name.append(getFileName()); 667 668 return mapping.getClassLoaderForArchive().getResourceAsStream(name.toString()); 669 } 670 else { 671 return null; 672 } 673 } 674 @Override 675 public String[] getSource() throws IOException { 676 //if(source!=null) return source; 677 InputStream is = getSourceAsInputStream(); 678 if(is==null) return null; 679 try { 680 return IOUtil.toStringArray(IOUtil.getReader(is,getMapping().getConfig().getTemplateCharset())); 681 } 682 finally { 683 IOUtil.closeEL(is); 684 } 685 } 686 687 @Override 688 public boolean equals(Object obj) { 689 if(this==obj) return true; 690 if(!(obj instanceof PageSource)) return false; 691 return getClassName().equals(((PageSource)obj).getClassName()); 692 //return equals((PageSource)obj); 693 } 694 695 /** 696 * is given object equal to this 697 * @param other 698 * @return is same 699 */ 700 public boolean equals(PageSource other) { 701 if(this==other) return true; 702 return getClassName().equals(other.getClassName()); 703 } 704 705 @Override 706 public PageSource getRealPage(String realPath) { 707 if(realPath.equals(".") || realPath.equals(".."))realPath+='/'; 708 else realPath=realPath.replace('\\','/'); 709 RefBoolean _isOutSide=new RefBooleanImpl(isOutSide); 710 711 712 if(realPath.indexOf('/')==0) { 713 _isOutSide.setValue(false); 714 } 715 else if(realPath.startsWith("./")) { 716 realPath=mergeRealPathes(mapping,this.realPath, realPath.substring(2),_isOutSide); 717 } 718 else { 719 realPath=mergeRealPathes(mapping,this.realPath, realPath,_isOutSide); 720 } 721 return mapping.getPageSource(realPath,_isOutSide.toBooleanValue()); 722 } 723 724 @Override 725 public final void setLastAccessTime(long lastAccess) { 726 this.lastAccess=lastAccess; 727 } 728 729 @Override 730 public final long getLastAccessTime() { 731 return lastAccess; 732 } 733 734 @Override 735 public synchronized final void setLastAccessTime() { 736 accessCount++; 737 this.lastAccess=System.currentTimeMillis(); 738 } 739 740 @Override 741 public final int getAccessCount() { 742 return accessCount; 743 } 744 745 @Override 746 public Resource getResource() { 747 Resource p = getPhyscalFile(); 748 Resource a = getArchiveFile(); 749 if(mapping.isPhysicalFirst()){ 750 if(a==null) return p; 751 if(p==null) return a; 752 753 if(p.exists()) return p; 754 if(a.exists()) return a; 755 return p; 756 } 757 if(p==null) return a; 758 if(a==null) return p; 759 760 if(a.exists()) return a; 761 if(p.exists()) return p; 762 return a; 763 764 //return getArchiveFile(); 765 } 766 767 @Override 768 public Resource getResourceTranslated(PageContext pc) throws ExpressionException { 769 Resource res = null; 770 if(!isLoad(LOAD_ARCHIVE)) res=getPhyscalFile(); 771 772 // there is no physical resource 773 if(res==null){ 774 String path=getDisplayPath(); 775 if(path!=null){ 776 if(path.startsWith("ra://")) 777 path="zip://"+path.substring(5); 778 res=ResourceUtil.toResourceNotExisting(pc, path,false); 779 } 780 } 781 return res; 782 } 783 784 785 public void clear() { 786 if(page!=null){ 787 page=null; 788 } 789 } 790 791 /** 792 * clear page, but only when page use the same clasloader as provided 793 * @param cl 794 */ 795 public void clear(ClassLoader cl) { 796 if(page!=null && page.getClass().getClassLoader().equals(cl)){ 797 page=null; 798 } 799 } 800 801 @Override 802 public String getFullClassName() { 803 String s=_getFullClassName(); 804 return s; 805 } 806 807 public String _getFullClassName() { 808 String p=getPackageName(); 809 if(p.length()==0) return getClassName(); 810 return p.concat(".").concat(getClassName()); 811 } 812 813 public boolean isLoad() { 814 return page!=null;////load!=LOAD_NONE; 815 } 816 817 @Override 818 public String toString() { 819 return getDisplayPath(); 820 } 821 822 @Override 823 public long sizeOf() { 824 return SizeOf.size(page,0)+ 825 SizeOf.size(className)+ 826 SizeOf.size(packageName)+ 827 SizeOf.size(javaName)+ 828 SizeOf.size(fileName)+ 829 SizeOf.size(compName)+ 830 SizeOf.size(lastAccess)+ 831 SizeOf.size(accessCount); 832 } 833 834 public static PageSource best(PageSource[] arr) { 835 if(ArrayUtil.isEmpty(arr)) return null; 836 if(arr.length==1)return arr[0]; 837 for(int i=0;i<arr.length;i++) { 838 if(pageExist(arr[i])) return arr[i]; 839 } 840 /*// get the best none existing 841 for(int i=0;i<arr.length;i++) { 842 if(arr[i].getPhyscalFile()!=null) return arr[i]; 843 } 844 for(int i=0;i<arr.length;i++) { 845 if(arr[i].getDisplayPath()!=null) return arr[i]; 846 } 847 */ 848 return arr[0]; 849 } 850 851 public static boolean pageExist(PageSource ps) { 852 return (ps.getMapping().isTrusted() && ((PageSourceImpl)ps).isLoad()) || ps.exists(); 853 } 854 855 public static Page loadPage(PageContext pc,PageSource[] arr,Page defaultValue) throws PageException { 856 if(ArrayUtil.isEmpty(arr)) return null; 857 Page p; 858 for(int i=0;i<arr.length;i++) { 859 p=arr[i].loadPage(pc,(Page)null); 860 if(p!=null) return p; 861 } 862 return defaultValue; 863 } 864 865 public static Page loadPage(PageContext pc,PageSource[] arr) throws PageException { 866 if(ArrayUtil.isEmpty(arr)) return null; 867 868 Page p; 869 for(int i=0;i<arr.length;i++) { 870 p=arr[i].loadPage(pc,null); 871 if(p!=null) return p; 872 } 873 throw new MissingIncludeException(arr[0]); 874 } 875 876 877 878 }