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