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    }