001/**
002 *
003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved.
004 *
005 * This library is free software; you can redistribute it and/or
006 * modify it under the terms of the GNU Lesser General Public
007 * License as published by the Free Software Foundation; either 
008 * version 2.1 of the License, or (at your option) any later version.
009 * 
010 * This library is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013 * Lesser General Public License for more details.
014 * 
015 * You should have received a copy of the GNU Lesser General Public 
016 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
017 * 
018 **/
019package lucee.runtime.type.scope.storage.clean;
020
021import java.io.IOException;
022
023import lucee.commons.io.IOUtil;
024import lucee.commons.io.res.Resource;
025import lucee.commons.io.res.filter.AndResourceFilter;
026import lucee.commons.io.res.filter.DirectoryResourceFilter;
027import lucee.commons.io.res.filter.ExtensionResourceFilter;
028import lucee.commons.io.res.filter.ResourceFilter;
029import lucee.commons.io.res.util.ResourceUtil;
030import lucee.commons.lang.ExceptionUtil;
031import lucee.runtime.config.ConfigWebImpl;
032import lucee.runtime.op.Caster;
033import lucee.runtime.type.dt.DateTimeImpl;
034import lucee.runtime.type.scope.Scope;
035import lucee.runtime.type.scope.storage.StorageScopeEngine;
036import lucee.runtime.type.scope.storage.StorageScopeFile;
037import lucee.runtime.type.scope.storage.StorageScopeListener;
038
039public class FileStorageScopeCleaner extends StorageScopeCleanerSupport {
040        
041        private static final ResourceFilter DIR_FILTER = new DirectoryResourceFilter();
042        private static ExtensionResourceFilter EXT_FILTER = new ExtensionResourceFilter(".scpt",true);
043        
044        
045        
046
047
048        public FileStorageScopeCleaner(int type,StorageScopeListener listener) {
049                super(type,listener,INTERVALL_DAY);
050        }
051        
052        @Override
053        public void init(StorageScopeEngine engine){
054                super.init(engine);
055        }
056
057        @Override
058        protected void _clean() {
059                ConfigWebImpl cwi=(ConfigWebImpl) engine.getFactory().getConfig();
060                Resource dir=type==Scope.SCOPE_CLIENT?cwi.getClientScopeDir():cwi.getSessionScopeDir();
061                
062                // for old files only the defintion from admin can be used
063                long timeout=type==Scope.SCOPE_CLIENT?cwi.getClientTimeout().getMillis():cwi.getSessionTimeout().getMillis();
064                long time = new DateTimeImpl(cwi).getTime()-timeout;
065                
066                try {
067                        // delete files that has expired
068                        AndResourceFilter andFilter = new AndResourceFilter(new ResourceFilter[]{EXT_FILTER,new ExpiresFilter(time,true)});
069                        String appName,cfid2,cfid;
070                        Resource[] apps = dir.listResources(DIR_FILTER),cfidDir,files;
071                        
072                        if(apps!=null)for(int a=0;a<apps.length;a++){
073                                appName=StorageScopeFile.decode(apps[a].getName());
074                                cfidDir=apps[a].listResources(DIR_FILTER);
075                                if(cfidDir!=null)for(int b=0;b<cfidDir.length;b++){
076                                        cfid2=cfidDir[b].getName();
077                                        files=cfidDir[b].listResources(andFilter);
078                                        if(files!=null){
079                                                for(int c=0;c<files.length;c++){
080                                                        cfid=files[c].getName();
081                                                        cfid=cfid2+cfid.substring(0,cfid.length()-5);
082                                                        
083                                                        if(listener!=null)listener.doEnd(engine,this, appName, cfid);
084                                                        
085                                                        //info("remove from memory "+appName+"/"+cfid);
086                                                        engine.remove(type,appName,cfid);
087                                                        
088                                                        info("remove file "+files[c]);
089                                                        files[c].delete();
090                                                }
091                                        }
092                                }
093                        }
094                        
095                        ResourceUtil.removeEmptyFolders(dir,null);
096                
097                } catch (Throwable t) {
098                        ExceptionUtil.rethrowIfNecessary(t);
099                        error(t);
100                }
101
102                
103                //long maxSize = type==Scope.SCOPE_CLIENT?cwi.getClientScopeDirSize():cwi.getSessionScopeDirSize();
104                //checkSize(config,dir,maxSize,extfilter);
105        }
106        
107
108        static class ExpiresFilter implements ResourceFilter {
109
110                private long time;
111                private boolean allowDir;
112
113                public ExpiresFilter(long time, boolean allowDir) {
114                        this.allowDir=allowDir;
115                        this.time=time;
116                }
117
118                public boolean accept(Resource res) {
119
120                        if(res.isDirectory()) return allowDir;
121                        
122                        // load content
123                        String str=null;
124                        try {
125                                str = IOUtil.toString(res,"UTF-8");
126                        } 
127                        catch (IOException e) {
128                                return false;
129                        }
130                        
131                        int index=str.indexOf(':');
132                        if(index!=-1){
133                                long expires=Caster.toLongValue(str.substring(0,index),-1L);
134                                // check is for backward compatibility, old files have no expires date inside. they do ot expire
135                                if(expires!=-1) {
136                                        if(expires<System.currentTimeMillis()){
137                                                return true;
138                                        }
139                                        str=str.substring(index+1);
140                                        return false;
141                                }
142                        }
143                        // old files not having a timestamp inside
144                        else if(res.lastModified()<=time) {
145                                return true;
146                                
147                        }
148                        return false;
149                }
150        
151    }
152
153
154}