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.cache;
020
021import java.io.IOException;
022import java.util.ArrayList;
023import java.util.Date;
024import java.util.Iterator;
025import java.util.List;
026
027import lucee.commons.io.cache.Cache;
028import lucee.commons.io.cache.CacheEntry;
029import lucee.commons.io.cache.CacheEntryFilter;
030import lucee.commons.io.cache.CacheKeyFilter;
031import lucee.commons.io.cache.exp.CacheException;
032import lucee.runtime.type.Struct;
033
034public abstract class CacheSupport implements Cache {
035
036        @Override
037        public List<String> keys(CacheKeyFilter filter) throws IOException {
038                boolean all=CacheUtil.allowAll(filter);
039                
040                List<String> keys = keys();
041                List<String> list=new ArrayList<String>();
042                Iterator<String> it = keys.iterator();
043                String key;
044                while(it.hasNext()){
045                        key= it.next();
046                        if(all || filter.accept(key))list.add(key);
047                }
048                return list;
049        }
050        
051        @Override
052        public List<String> keys(CacheEntryFilter filter) throws IOException {
053                boolean all=CacheUtil.allowAll(filter);
054                
055                List<String> keys = keys();
056                List<String> list=new ArrayList<String>();
057                Iterator<String> it = keys.iterator();
058                String key;
059                CacheEntry entry;
060                while(it.hasNext()){
061                        key=it.next();
062                        entry=getQuiet(key,null);
063                        if(all || filter.accept(entry))list.add(key);
064                }
065                return list;
066        }
067        
068        @Override
069        public List<CacheEntry> entries() throws IOException {
070                List<String> keys = keys();
071                List<CacheEntry> list=new ArrayList<CacheEntry>();
072                Iterator<String> it = keys.iterator();
073                while(it.hasNext()){
074                        list.add(getQuiet(it.next(),null));
075                }
076                return list;
077        }
078        
079        @Override
080        public List<CacheEntry> entries(CacheKeyFilter filter) throws IOException {
081                List<String> keys = keys();
082                List<CacheEntry> list=new ArrayList<CacheEntry>();
083                Iterator<String> it = keys.iterator();
084                String key;
085                while(it.hasNext()){
086                        key=it.next();
087                        if(filter.accept(key))list.add(getQuiet(key,null));
088                }
089                return list;
090        }
091        
092        @Override
093        public List<CacheEntry> entries(CacheEntryFilter filter) throws IOException {
094                List<String> keys = keys();
095                List<CacheEntry> list=new ArrayList<CacheEntry>();
096                Iterator<String> it = keys.iterator();
097                CacheEntry entry;
098                while(it.hasNext()){
099                        entry=getQuiet(it.next(),null);
100                        if(filter.accept(entry))list.add(entry);
101                }
102                return list;
103        }
104
105        // there was the wrong generic type defined in the older interface, because of that we do not define a generic type at all here, just to be sure
106        @Override
107        public List values() throws IOException {
108                List<String> keys = keys();
109                List<Object> list=new ArrayList<Object>();
110                Iterator<String> it = keys.iterator();
111                String key;
112                while(it.hasNext()){
113                        key=it.next();
114                        list.add(getQuiet(key,null).getValue());
115                }
116                return list;
117        }
118
119        // there was the wrong generic type defined in the older interface, because of that we do not define a generic type at all here, just to be sure
120        @Override
121        public List values(CacheEntryFilter filter) throws IOException {
122                if(CacheUtil.allowAll(filter)) return values();
123                
124                List<String> keys = keys();
125                List<Object> list=new ArrayList<Object>();
126                Iterator<String> it = keys.iterator();
127                String key;
128                CacheEntry entry;
129                while(it.hasNext()){
130                        key=it.next();
131                        entry=getQuiet(key,null);
132                        if(filter.accept(entry))list.add(entry.getValue());
133                }
134                return list;
135        }
136
137        // there was the wrong generic type defined in the older interface, because of that we do not define a generic type at all here, just to be sure
138        @Override
139        public List values(CacheKeyFilter filter) throws IOException {
140                if(CacheUtil.allowAll(filter)) return values();
141                
142                List<String> keys = keys();
143                List<Object> list=new ArrayList<Object>();
144                Iterator<String> it = keys.iterator();
145                String key;
146                while(it.hasNext()){
147                        key=it.next();
148                        if(filter.accept(key))list.add(getQuiet(key,null).getValue());
149                }
150                return list;
151        }
152        
153        @Override
154        public int remove(CacheEntryFilter filter) throws IOException {
155                if(CacheUtil.allowAll(filter)) return clear();
156                
157                List<String> keys = keys();
158                int count=0;
159                Iterator<String> it = keys.iterator();
160                String key;
161                CacheEntry entry;
162                while(it.hasNext()){
163                        key=it.next();
164                        entry=getQuiet(key,null);
165                        if(filter==null || filter.accept(entry)){
166                                remove(key);
167                                count++;
168                        }
169                }
170                return count;
171        }
172        
173
174        @Override
175        public int remove(CacheKeyFilter filter) throws IOException {
176                if(CacheUtil.allowAll(filter)) return clear();
177                
178                
179                List<String> keys = keys();
180                int count=0;
181                Iterator<String> it = keys.iterator();
182                String key;
183                while(it.hasNext()){
184                        key=it.next();
185                        if(filter==null || filter.accept(key)){
186                                remove(key);
187                                count++;
188                        }
189                }
190                return count;
191        }
192        
193        public Struct getCustomInfo() {
194                return CacheUtil.getInfo(this);
195        }
196        
197
198        @Override
199        public Object getValue(String key) throws IOException {
200                return getCacheEntry(key).getValue();
201        }
202
203        @Override
204        public Object getValue(String key, Object defaultValue) {
205                CacheEntry entry = getCacheEntry(key,null);
206                if(entry==null) return defaultValue;
207                return entry.getValue();
208        } 
209        
210        protected static boolean valid(CacheEntry entry) {
211                long now = System.currentTimeMillis();
212                if(entry.liveTimeSpan()>0 && entry.liveTimeSpan()+getTime(entry.lastModified())<now){
213                        return false;
214                }
215                if(entry.idleTimeSpan()>0 && entry.idleTimeSpan()+getTime(entry.lastHit())<now){
216                        return false;
217                }
218                return true;
219        }
220        
221        private static long getTime(Date date) {
222                return date==null?0:date.getTime();
223        }
224
225        @Override
226        public CacheEntry getCacheEntry(String key) throws IOException {
227                CacheEntry entry = getCacheEntry(key, null);
228                if(entry==null) throw new CacheException("there is no valid cache entry with key ["+key+"]");
229                return entry;
230        }
231        
232        public CacheEntry getQuiet(String key) throws IOException {
233                CacheEntry entry = getQuiet(key, null);
234                if(entry==null) throw new CacheException("there is no valid cache entry with key ["+key+"]");
235                return entry;
236        }
237
238        public abstract CacheEntry getQuiet(String key, CacheEntry defaultValue);
239        
240        /**
241         * remove all entries 
242         * @return returns the count of the removal or -1 if this information is not available
243         */
244        public abstract int clear() throws IOException ;
245        
246
247}