001 package railo.runtime.tag; 002 003 import java.io.File; 004 import java.io.IOException; 005 import java.util.Date; 006 007 import org.apache.oro.text.regex.MalformedPatternException; 008 009 import railo.commons.io.ModeUtil; 010 import railo.commons.io.res.Resource; 011 import railo.commons.io.res.ResourceMetaData; 012 import railo.commons.io.res.filter.AndResourceFilter; 013 import railo.commons.io.res.filter.DirectoryResourceFilter; 014 import railo.commons.io.res.filter.FileResourceFilter; 015 import railo.commons.io.res.filter.ResourceFilter; 016 import railo.commons.io.res.filter.ResourceNameFilter; 017 import railo.commons.io.res.type.file.FileResource; 018 import railo.commons.io.res.type.s3.S3; 019 import railo.commons.io.res.type.s3.S3Constants; 020 import railo.commons.io.res.type.s3.S3Exception; 021 import railo.commons.io.res.type.s3.S3Resource; 022 import railo.commons.io.res.util.ModeObjectWrap; 023 import railo.commons.io.res.util.ResourceAndResourceNameFilter; 024 import railo.commons.io.res.util.ResourceUtil; 025 import railo.commons.io.res.util.UDFFilter; 026 import railo.commons.io.res.util.WildCardFilter; 027 import railo.commons.lang.StringUtil; 028 import railo.runtime.PageContext; 029 import railo.runtime.exp.ApplicationException; 030 import railo.runtime.exp.PageException; 031 import railo.runtime.ext.tag.TagImpl; 032 import railo.runtime.functions.s3.StoreSetACL; 033 import railo.runtime.op.Caster; 034 import railo.runtime.op.Decision; 035 import railo.runtime.security.SecurityManager; 036 import railo.runtime.type.Array; 037 import railo.runtime.type.ArrayImpl; 038 import railo.runtime.type.Collection.Key; 039 import railo.runtime.type.KeyImpl; 040 import railo.runtime.type.Query; 041 import railo.runtime.type.QueryImpl; 042 import railo.runtime.type.UDF; 043 044 /** 045 * Handles interactions with directories. 046 * 047 * 048 * 049 **/ 050 public final class Directory extends TagImpl { 051 052 public static final int TYPE_ALL = 0; 053 public static final int TYPE_FILE = 1; 054 public static final int TYPE_DIR = 2; 055 056 public static final ResourceFilter DIRECTORY_FILTER = new DirectoryResourceFilter(); 057 public static final ResourceFilter FILE_FILTER = new FileResourceFilter(); 058 059 private static final Key MODE = KeyImpl.intern("mode"); 060 private static final Key META = KeyImpl.intern("meta"); 061 private static final Key DATE_LAST_MODIFIED = KeyImpl.intern("dateLastModified"); 062 private static final Key ATTRIBUTES = KeyImpl.intern("attributes"); 063 private static final Key DIRECTORY = KeyImpl.intern("directory"); 064 065 066 public static final int LIST_INFO_QUERY_ALL = 1; 067 public static final int LIST_INFO_QUERY_NAME = 2; 068 public static final int LIST_INFO_ARRAY_NAME = 4; 069 public static final int LIST_INFO_ARRAY_PATH = 8; 070 071 /** Optional for action = "list". Ignored by all other actions. File extension filter applied to 072 ** returned names. For example: *m. Only one mask filter can be applied at a time. */ 073 private ResourceFilter filter; 074 private ResourceAndResourceNameFilter nameFilter; 075 076 /** The name of the directory to perform the action against. */ 077 private Resource directory; 078 079 /** Defines the action to be taken with directory(ies) specified in directory. */ 080 private String action="list"; 081 082 /** Optional for action = "list". Ignored by all other actions. The query columns by which to sort 083 ** the directory listing. Any combination of columns from query output can be specified in comma-separated list. 084 ** You can specify ASC (ascending) or DESC (descending) as qualifiers for column names. ASC is the default */ 085 private String sort; 086 087 /** Used with action = "Create" to define the permissions for a directory on UNIX and Linux 088 ** platforms. Ignored on Windows. Options correspond to the octal values of the UNIX chmod command. From 089 ** left to right, permissions are assigned for owner, group, and other. */ 090 private int mode=-1; 091 092 /** Required for action = "rename". Ignored by all other actions. The new name of the directory 093 ** specified in the directory attribute. */ 094 private String strNewdirectory; 095 096 /** Required for action = "list". Ignored by all other actions. Name of output query for directory 097 ** listing. */ 098 private String name=null; 099 100 101 private boolean recurse=false; 102 103 private String serverPassword; 104 105 private int type=TYPE_ALL; 106 //private boolean listOnlyNames; 107 private int listInfo=LIST_INFO_QUERY_ALL; 108 //private int acl=S3Constants.ACL_UNKNOW; 109 private Object acl=null; 110 private int storage=S3Constants.STORAGE_UNKNOW; 111 112 113 114 /** 115 * @see javax.servlet.jsp.tagext.Tag#release() 116 */ 117 public void release() { 118 super.release(); 119 acl=null; 120 storage=S3Constants.STORAGE_UNKNOW; 121 122 123 type=TYPE_ALL; 124 filter=null; 125 nameFilter=null; 126 directory=null; 127 action="list"; 128 sort=null; 129 mode=-1; 130 strNewdirectory=null; 131 name=null; 132 recurse=false; 133 serverPassword=null; 134 listInfo=LIST_INFO_QUERY_ALL; 135 } 136 137 138 139 /** 140 * sets a filter 141 * @param pattern 142 * @throws PageException 143 **/ 144 145 146 147 public static ResourceAndResourceNameFilter createFilter(Object filter) throws PageException { 148 if(filter instanceof UDF) 149 return createFilter((UDF)filter); 150 return createFilter(Caster.toString(filter)); 151 } 152 153 154 public static ResourceAndResourceNameFilter createFilter(UDF filter) throws PageException { 155 return new UDFFilter(filter); 156 } 157 158 public static ResourceAndResourceNameFilter createFilter(String pattern) throws PageException { 159 if(pattern.trim().length()>0) { 160 try { 161 return new WildCardFilter(pattern); 162 } catch (MalformedPatternException e) { 163 throw Caster.toPageException(e); 164 } 165 } 166 return null; 167 } 168 169 170 171 public void setFilter(Object filter) throws PageException { 172 this.filter=nameFilter=createFilter(filter); 173 } 174 175 public void setFilter(UDF filter) throws PageException { 176 this.filter=nameFilter=createFilter(filter); 177 } 178 public void setFilter(String pattern) throws PageException { 179 this.filter=nameFilter=createFilter(pattern); 180 } 181 182 /** set the value acl 183 * used only for s3 resources, for all others ignored 184 * @param charset value to set 185 * @throws ApplicationException 186 * @Deprecated only exists for backward compatibility to old ra files. 187 **/ 188 public void setAcl(String acl) throws ApplicationException { 189 this.acl=acl; 190 /*acl=acl.trim().toLowerCase(); 191 192 if("private".equals(acl)) this.acl=S3Constants.ACL_PRIVATE; 193 else if("public-read".equals(acl)) this.acl=S3Constants.ACL_PRIVATE; 194 else if("public-read-write".equals(acl)) this.acl=S3Constants.ACL_PUBLIC_READ_WRITE; 195 else if("authenticated-read".equals(acl)) this.acl=S3Constants.ACL_AUTH_READ; 196 197 else throw new ApplicationException("invalid value for attribute acl ["+acl+"]", 198 "valid values are [private,public-read,public-read-write,authenticated-read]");*/ 199 } 200 201 public void setAcl(Object acl) throws ApplicationException { 202 this.acl=acl; 203 } 204 205 public void setStoreacl(Object acl) throws ApplicationException { 206 this.acl=acl; 207 } 208 209 /** set the value storage 210 * used only for s3 resources, for all others ignored 211 * @param charset value to set 212 * @throws PageException 213 **/ 214 public void setStorage(String storage) throws PageException { 215 try { 216 this.storage=S3.toIntStorage(storage); 217 } catch (S3Exception e) { 218 throw Caster.toPageException(e); 219 } 220 } 221 public void setStorelocation(String storage) throws PageException { 222 setStorage(storage); 223 } 224 225 226 227 public void setServerpassword(String serverPassword) { 228 this.serverPassword=serverPassword; 229 } 230 231 232 public void setListinfo(String strListinfo) { 233 strListinfo=strListinfo.trim().toLowerCase(); 234 this.listInfo="name".equals(strListinfo)?LIST_INFO_QUERY_NAME:LIST_INFO_QUERY_ALL; 235 236 237 238 239 240 } 241 242 243 244 /** set the value directory 245 * The name of the directory to perform the action against. 246 * @param directory value to set 247 **/ 248 public void setDirectory(String directory) { 249 250 this.directory=ResourceUtil.toResourceNotExisting(pageContext ,directory); 251 //print.ln(this.directory); 252 } 253 254 /** set the value action 255 * Defines the action to be taken with directory(ies) specified in directory. 256 * @param action value to set 257 **/ 258 public void setAction(String action) { 259 this.action=action.toLowerCase(); 260 } 261 262 /** set the value sort 263 * Optional for action = "list". Ignored by all other actions. The query columns by which to sort 264 * the directory listing. Any combination of columns from query output can be specified in comma-separated list. 265 * You can specify ASC (ascending) or DESC (descending) as qualifiers for column names. ASC is the default 266 * @param sort value to set 267 **/ 268 public void setSort(String sort) { 269 if(sort.trim().length()>0) 270 this.sort=sort; 271 } 272 273 /** set the value mode 274 * Used with action = "Create" to define the permissions for a directory on UNIX and Linux 275 * platforms. Ignored on Windows. Options correspond to the octal values of the UNIX chmod command. From 276 * left to right, permissions are assigned for owner, group, and other. 277 * @param mode value to set 278 * @throws PageException 279 **/ 280 public void setMode(String mode) throws PageException { 281 try { 282 this.mode=ModeUtil.toOctalMode(mode); 283 } 284 catch (IOException e) { 285 throw Caster.toPageException(e); 286 } 287 } 288 289 /** set the value newdirectory 290 * Required for action = "rename". Ignored by all other actions. The new name of the directory 291 * specified in the directory attribute. 292 * @param newdirectory value to set 293 **/ 294 public void setNewdirectory(String newdirectory) { 295 //this.newdirectory=ResourceUtil.toResourceNotExisting(pageContext ,newdirectory); 296 this.strNewdirectory=newdirectory; 297 } 298 299 /** set the value name 300 * Required for action = "list". Ignored by all other actions. Name of output query for directory 301 * listing. 302 * @param name value to set 303 **/ 304 public void setName(String name) { 305 this.name=name; 306 } 307 308 /** 309 * @param recurse The recurse to set. 310 */ 311 public void setRecurse(boolean recurse) { 312 this.recurse = recurse; 313 } 314 315 316 /** 317 * @see javax.servlet.jsp.tagext.Tag#doStartTag() 318 */ 319 public int doStartTag() throws PageException { 320 321 //securityManager = pageContext.getConfig().getSecurityManager(); 322 if(action.equals("list")) { 323 Object res=actionList(pageContext,directory,serverPassword,type,filter,nameFilter,listInfo,recurse,sort); 324 if(!StringUtil.isEmpty(name) && res!=null)pageContext.setVariable(name,res); 325 } 326 else if(action.equals("create")) actionCreate(pageContext,directory,serverPassword,true,mode,acl,storage); 327 else if(action.equals("delete")) actionDelete(pageContext,directory,recurse,serverPassword); 328 else if(action.equals("forcedelete")) actionDelete(pageContext,directory,true,serverPassword); 329 else if(action.equals("rename")) actionRename(pageContext,directory,strNewdirectory,serverPassword,acl,storage); 330 else throw new ApplicationException("invalid action ["+action+"] for the tag directory"); 331 332 return SKIP_BODY; 333 } 334 335 336 /** 337 * @see javax.servlet.jsp.tagext.Tag#doEndTag() 338 */ 339 public int doEndTag() { 340 return EVAL_PAGE; 341 } 342 343 /** 344 * list all files and directories inside a directory 345 * @throws PageException 346 */ 347 public static Object actionList(PageContext pageContext,Resource directory, String serverPassword, int type,ResourceFilter filter,ResourceAndResourceNameFilter nameFilter, 348 int listInfo,boolean recurse,String sort) throws PageException { 349 // check directory 350 SecurityManager securityManager = pageContext.getConfig().getSecurityManager(); 351 securityManager.checkFileLocation(pageContext.getConfig(),directory,serverPassword); 352 353 if(type!=TYPE_ALL) { 354 ResourceFilter typeFilter = (type==TYPE_DIR)?DIRECTORY_FILTER:FILE_FILTER; 355 if(filter==null) filter=typeFilter; 356 else filter=new AndResourceFilter(new ResourceFilter[]{typeFilter,filter}); 357 } 358 359 360 // create query Object 361 String[] names = new String[]{"name","size","type","dateLastModified","attributes","mode","directory"}; 362 String[] types=new String[]{"VARCHAR","DOUBLE","VARCHAR","DATE","VARCHAR","VARCHAR","VARCHAR"}; 363 364 boolean hasMeta=directory instanceof ResourceMetaData; 365 if(hasMeta){ 366 names = new String[]{"name","size","type","dateLastModified","attributes","mode","directory","meta"}; 367 types=new String[]{"VARCHAR","DOUBLE","VARCHAR","DATE","VARCHAR","VARCHAR","VARCHAR","OBJECT"}; 368 } 369 Array array=null; 370 Query query=null; 371 Object rtn; 372 if(listInfo==LIST_INFO_QUERY_ALL || listInfo==LIST_INFO_QUERY_NAME){ 373 boolean listOnlyNames=listInfo==LIST_INFO_QUERY_NAME; 374 rtn=query=new QueryImpl( 375 listOnlyNames?new String[]{"name"}:names, 376 listOnlyNames?new String[]{"VARCHAR"}:types, 377 0,"query"); 378 } 379 else 380 rtn=array=new ArrayImpl(); 381 382 if(!directory.exists()){ 383 if(directory instanceof FileResource) return rtn; 384 throw new ApplicationException("directory ["+directory.toString()+"] doesn't exist"); 385 } 386 if(!directory.isDirectory()){ 387 if(directory instanceof FileResource) return rtn; 388 throw new ApplicationException("file ["+directory.toString()+"] exists, but isn't a directory"); 389 } 390 if(!directory.isReadable()){ 391 if(directory instanceof FileResource) return rtn; 392 throw new ApplicationException("no access to read directory ["+directory.toString()+"]"); 393 } 394 395 long start=System.currentTimeMillis(); 396 397 try { 398 // Query All 399 if(listInfo==LIST_INFO_QUERY_ALL) 400 _fillQueryAll(query,directory,filter,0,hasMeta,recurse); 401 402 // Query Name 403 else if(listInfo==LIST_INFO_QUERY_NAME) { 404 if(recurse || type!=TYPE_ALL)_fillQueryNamesRec("",query, directory, filter, 0,recurse); 405 else _fillQueryNames(query, directory, nameFilter, 0); 406 } 407 408 //Array Name/Path 409 else if(listInfo==LIST_INFO_ARRAY_NAME || listInfo==LIST_INFO_ARRAY_PATH) { 410 boolean onlyName=listInfo==LIST_INFO_ARRAY_NAME; 411 if(!onlyName || recurse || type!=TYPE_ALL)_fillArrayPathOrName(array, directory, nameFilter, 0, recurse, onlyName);//QueryNamesRec("",query, directory, filter, 0,recurse); 412 else _fillArrayName(array, directory, nameFilter, 0); 413 } 414 415 416 } catch (IOException e) { 417 throw Caster.toPageException(e); 418 } 419 420 // sort 421 if(sort!=null && query!=null) { 422 String[] arr=sort.toLowerCase().split(","); 423 for(int i=arr.length-1;i>=0;i--) { 424 try { 425 String[] col=arr[i].trim().split("\\s+"); 426 if(col.length==1)query.sort(col[0].trim()); 427 else if(col.length==2) { 428 String order=col[1].toLowerCase().trim(); 429 if(order.equals("asc")) 430 query.sort(col[0],railo.runtime.type.Query.ORDER_ASC); 431 else if(order.equals("desc")) 432 query.sort(col[0],railo.runtime.type.Query.ORDER_DESC); 433 else 434 throw new ApplicationException("invalid order type ["+col[1]+"]"); 435 } 436 } 437 catch(Throwable t) {} 438 } 439 } 440 if(query!=null)query.setExecutionTime(System.currentTimeMillis()-start); 441 return rtn; 442 } 443 444 445 446 447 private static int _fillQueryAll(Query query, Resource directory, ResourceFilter filter, int count, boolean hasMeta, boolean recurse) throws PageException, IOException { 448 //long start=System.currentTimeMillis(); 449 Resource[] list=directory.listResources(); 450 451 if(list==null || list.length==0) return count; 452 String dir=directory.getCanonicalPath(); 453 // fill data to query 454 //query.addRow(list.length); 455 boolean isDir; 456 for(int i=0;i<list.length;i++) { 457 if(filter==null || filter.accept(list[i])) { 458 query.addRow(1); 459 count++; 460 query.setAt(KeyImpl.NAME,count,list[i].getName()); 461 isDir=list[i].isDirectory(); 462 query.setAt(KeyImpl.SIZE,count,new Double(isDir?0:list[i].length())); 463 query.setAt(KeyImpl.TYPE,count,isDir?"Dir":"File"); 464 if(directory.getResourceProvider().isModeSupported()){ 465 466 query.setAt(MODE,count,new ModeObjectWrap(list[i])); 467 } 468 query.setAt(DATE_LAST_MODIFIED,count,new Date(list[i].lastModified())); 469 query.setAt(ATTRIBUTES,count,getFileAttribute(list[i],true)); 470 471 if(hasMeta){ 472 query.setAt(META,count,((ResourceMetaData)list[i]).getMetaData()); 473 } 474 475 query.setAt(DIRECTORY,count,dir); 476 } 477 if(recurse && list[i].isDirectory()) 478 count=_fillQueryAll(query,list[i],filter,count,hasMeta,recurse); 479 } 480 return count; 481 } 482 // this method only exists for performance reasion 483 private static int _fillQueryNames(Query query, Resource directory, ResourceNameFilter filter, int count) throws PageException { 484 String[] list=directory.list(); 485 if(list==null || list.length==0) return count; 486 for(int i=0;i<list.length;i++) { 487 if(filter==null || filter.accept(directory,list[i])) { 488 query.addRow(1); 489 count++; 490 query.setAt(KeyImpl.NAME,count,list[i]); 491 } 492 } 493 return count; 494 } 495 496 private static int _fillQueryNamesRec(String parent, Query query, Resource directory, ResourceFilter filter, int count, boolean recurse) throws PageException { 497 Resource[] list=directory.listResources(); 498 if(list==null || list.length==0) return count; 499 for(int i=0;i<list.length;i++) { 500 if(filter==null || filter.accept(list[i])) { 501 query.addRow(1); 502 count++; 503 query.setAt(KeyImpl.NAME,count,parent.concat(list[i].getName())); 504 505 } 506 if(recurse && list[i].isDirectory()) 507 count=_fillQueryNamesRec(parent+list[i].getName()+"/",query,list[i],filter,count,recurse); 508 } 509 return count; 510 } 511 512 private static int _fillArrayPathOrName(Array arr, Resource directory, ResourceFilter filter, int count, boolean recurse,boolean onlyName) throws PageException { 513 Resource[] list=directory.listResources(); 514 if(list==null || list.length==0) return count; 515 for(int i=0;i<list.length;i++) { 516 if(filter==null || filter.accept(list[i])) { 517 arr.appendEL(onlyName?list[i].getName():list[i].getAbsolutePath()); 518 count++; 519 520 } 521 if(recurse && list[i].isDirectory()) 522 count=_fillArrayPathOrName(arr,list[i],filter,count,recurse,onlyName); 523 } 524 return count; 525 } 526 527 // this method only exists for performance reasion 528 private static int _fillArrayName(Array arr, Resource directory, ResourceNameFilter filter, int count) { 529 String[] list=directory.list(); 530 if(list==null || list.length==0) return count; 531 for(int i=0;i<list.length;i++) { 532 if(filter==null || filter.accept(directory,list[i])) { 533 arr.appendEL(list[i]); 534 } 535 } 536 return count; 537 } 538 539 540 541 /** 542 * create a directory 543 * @throws PageException 544 */ 545 public static void actionCreate(PageContext pc,Resource directory,String serverPassword, boolean doParent,int mode,Object acl,int storage) throws PageException { 546 547 SecurityManager securityManager = pc.getConfig().getSecurityManager(); 548 securityManager.checkFileLocation(pc.getConfig(),directory,serverPassword); 549 550 if(directory.exists()) { 551 if(directory.isDirectory()) 552 throw new ApplicationException("directory ["+directory.toString()+"] already exist"); 553 else if(directory.isFile()) 554 throw new ApplicationException("can't create directory ["+directory.toString()+"], it exist a file with same name"); 555 } 556 //if(!directory.mkdirs()) throw new ApplicationException("can't create directory ["+directory.toString()+"]"); 557 try { 558 directory.createDirectory(doParent); 559 } catch (IOException ioe) { 560 throw Caster.toPageException(ioe); 561 } 562 563 // set S3 stuff 564 setS3Attrs(directory,acl,storage); 565 566 // Set Mode 567 if(mode!=-1) { 568 try { 569 directory.setMode(mode); 570 //FileUtil.setMode(directory,mode); 571 } catch (IOException e) { 572 throw Caster.toPageException(e); 573 } 574 } 575 } 576 577 private static void setS3Attrs(Resource res,Object acl,int storage) throws PageException { 578 String scheme = res.getResourceProvider().getScheme(); 579 580 if("s3".equalsIgnoreCase(scheme)){ 581 S3Resource s3r=(S3Resource) res; 582 if(acl!=null){ 583 try { 584 // old way 585 if(Decision.isString(acl)) { 586 if(Decision.isInteger(acl)) s3r.setACL(Caster.toIntValue(acl)); 587 else s3r.setACL(S3.toIntACL(Caster.toString(acl))); 588 } 589 // new way 590 else { 591 StoreSetACL.invoke(s3r, acl); 592 } 593 } catch (IOException e) { 594 throw Caster.toPageException(e); 595 } 596 } 597 598 if(storage!=S3Constants.STORAGE_UNKNOW) s3r.setStorage(storage); 599 } 600 } 601 602 603 604 /** 605 * delete directory 606 * @param dir 607 * @param forceDelete 608 * @throws PageException 609 */ 610 public static void actionDelete(PageContext pc,Resource dir, boolean forceDelete,String serverPassword) throws PageException { 611 SecurityManager securityManager = pc.getConfig().getSecurityManager(); 612 securityManager.checkFileLocation(pc.getConfig(),dir,serverPassword); 613 614 // directory doesn't exist 615 if(!dir.exists()) { 616 if(dir.isDirectory()) 617 throw new ApplicationException("directory ["+dir.toString()+"] doesn't exist"); 618 else if(dir.isFile()) 619 throw new ApplicationException("file ["+dir.toString()+"] doesn't exist and isn't a directory"); 620 } 621 622 // check if file 623 if(dir.isFile()) 624 throw new ApplicationException("can't delete ["+dir.toString()+"], it isn't a directory it is a file"); 625 626 // delete directory 627 try { 628 dir.remove(forceDelete); 629 } catch (IOException e) { 630 throw Caster.toPageException(e); 631 } 632 } 633 634 /** 635 * rename a directory to a new Name 636 * @throws PageException 637 */ 638 public static void actionRename(PageContext pc,Resource directory,String strNewdirectory,String serverPassword, Object acl,int storage) throws PageException { 639 // check directory 640 SecurityManager securityManager = pc.getConfig().getSecurityManager(); 641 securityManager.checkFileLocation(pc.getConfig(),directory,serverPassword); 642 643 644 if(!directory.exists()) 645 throw new ApplicationException("the directory ["+directory.toString()+"] doesn't exist"); 646 if(!directory.isDirectory()) 647 throw new ApplicationException("the file ["+directory.toString()+"] exists, but it isn't a directory"); 648 if(!directory.canRead()) 649 throw new ApplicationException("no access to read directory ["+directory.toString()+"]"); 650 651 if(strNewdirectory==null) 652 throw new ApplicationException("the attribute [newDirectory] is not defined"); 653 654 // real to source 655 Resource newdirectory=toDestination(pc,strNewdirectory,directory); 656 657 securityManager.checkFileLocation(pc.getConfig(),newdirectory,serverPassword); 658 if(newdirectory.exists()) 659 throw new ApplicationException("new directory ["+newdirectory.toString()+"] already exists"); 660 try { 661 directory.moveTo(newdirectory); 662 } 663 catch(Throwable t) { 664 throw new ApplicationException(t.getMessage()); 665 } 666 667 // set S3 stuff 668 setS3Attrs(directory,acl,storage); 669 670 } 671 672 673 private static Resource toDestination(PageContext pageContext,String path, Resource source) { 674 if(source!=null && path.indexOf(File.separatorChar)==-1 && path.indexOf('/')==-1 && path.indexOf('\\')==-1) { 675 Resource p = source.getParentResource(); 676 if(p!=null)return p.getRealResource(path); 677 } 678 return ResourceUtil.toResourceNotExisting(pageContext ,path); 679 } 680 681 682 683 private static String getFileAttribute(Resource file, boolean exists){ 684 return exists && !file.isWriteable() ? "R".concat(file.isHidden() ? "H" : "") : file.isHidden() ? "H" : ""; 685 } 686 687 688 689 /** 690 * @param type the type to set 691 */ 692 public void setType(String strType) throws ApplicationException { 693 strType=strType.trim().toLowerCase(); 694 695 696 if("all".equals(strType)) type=TYPE_ALL; 697 else if("dir".equals(strType)) type=TYPE_DIR; 698 else if("directory".equals(strType)) type=TYPE_DIR; 699 else if("file".equals(strType)) type=TYPE_FILE; 700 else throw new ApplicationException("invalid type ["+strType+"] for the tag directory"); 701 702 } 703 704 705 706 }