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.eh;
020
021import java.io.ByteArrayInputStream;
022import java.io.IOException;
023import java.io.OutputStream;
024import java.util.HashMap;
025import java.util.HashSet;
026import java.util.Iterator;
027import java.util.Map;
028import java.util.Map.Entry;
029import java.util.Set;
030
031import lucee.commons.io.CharsetUtil;
032import lucee.commons.io.cache.CacheEntry;
033import lucee.commons.io.cache.exp.CacheException;
034import lucee.commons.io.res.Resource;
035import lucee.commons.io.res.filter.ResourceNameFilter;
036import lucee.commons.lang.ExceptionUtil;
037import lucee.loader.util.Util;
038import lucee.runtime.config.Config;
039import lucee.runtime.engine.ThreadLocalPageContext;
040import lucee.runtime.exp.ApplicationException;
041import lucee.runtime.exp.PageRuntimeException;
042import lucee.runtime.type.Struct;
043import lucee.runtime.type.util.CollectionUtil;
044import net.sf.ehcache.Cache;
045import net.sf.ehcache.CacheManager;
046import net.sf.ehcache.Element;
047import net.sf.ehcache.config.Configuration;
048import net.sf.ehcache.config.ConfigurationFactory;
049
050public class EHCache extends EHCacheSupport {
051        
052        private static final boolean DISK_PERSISTENT = true;
053        private static final boolean ETERNAL = false;
054        private static final int MAX_ELEMENTS_IN_MEMEORY = 10000;
055        private static final int MAX_ELEMENTS_ON_DISK = 10000000;
056        private static final String MEMORY_EVICTION_POLICY = "LRU";
057        private static final boolean OVERFLOW_TO_DISK = true;
058        private static final long TIME_TO_IDLE_SECONDS = 86400; 
059        private static final long TIME_TO_LIVE_SECONDS = 86400;
060        
061        private static final boolean REPLICATE_PUTS = true;
062        private static final boolean REPLICATE_PUTS_VIA_COPY = true;
063        private static final boolean REPLICATE_UPDATES = true;
064        private static final boolean REPLICATE_UPDATES_VIA_COPY = true;
065        private static final boolean REPLICATE_REMOVALS = true;
066        private static final boolean REPLICATE_ASYNC = true;
067        private static final int ASYNC_REP_INTERVAL = 1000; 
068        //private static Map managers=new HashMap();
069        private static Map<String,CacheManagerAndHash> managers=new HashMap<String,CacheManagerAndHash>();
070        
071        //private net.sf.ehcache.Cache cache;
072        private int hits;
073        private int misses;
074        private String cacheName;
075        private CacheManager manager;
076        private ClassLoader classLoader;
077
078
079        public static void init(Config config,String[] cacheNames,Struct[] arguments) throws IOException {
080                System.setProperty("net.sf.ehcache.enableShutdownHook", "true");
081                Thread.currentThread().setContextClassLoader(config.getClassLoader());
082
083                Resource dir = config.getConfigDir().getRealResource("ehcache"),hashDir;
084                if(!dir.isDirectory())dir.createDirectory(true);
085                String[] hashArgs=createHash(arguments);
086                
087                // create all xml
088                HashMap<String,String> mapXML = new HashMap<String,String>();
089                HashMap<String,CacheManagerAndHash> newManagers = new HashMap<String,CacheManagerAndHash>();
090                for(int i=0;i<hashArgs.length;i++){
091                        if(mapXML.containsKey(hashArgs[i])) continue;
092                        
093                        hashDir=dir.getRealResource(hashArgs[i]);
094                        String xml=createXML(hashDir.getAbsolutePath(), cacheNames,arguments,hashArgs,hashArgs[i]);
095                        String hash=MD5.getDigestAsString(xml);
096                        
097                        CacheManagerAndHash manager= managers.remove(hashArgs[i]);
098                        if(manager!=null && manager.hash.equals(hash)) {
099                                newManagers.put(hashArgs[i], manager);
100                        }       
101                        else mapXML.put(hashArgs[i], xml);
102                }
103                
104                // shutdown all existing managers that have changed
105                {
106                        Iterator<Entry<String, CacheManagerAndHash>> it = managers.entrySet().iterator();
107                        Entry<String, CacheManagerAndHash> entry;
108                        synchronized(managers){
109                                it = managers.entrySet().iterator();
110                                while(it.hasNext()){
111                                        entry= it.next();
112                                        if(entry.getKey().toString().startsWith(dir.getAbsolutePath())){
113                                                entry.getValue().manager.shutdown();
114                                        }
115                                        else newManagers.put(entry.getKey(), entry.getValue());
116                                        
117                                }
118                                managers=newManagers;
119                        }
120                }
121                
122                Iterator<Entry<String, String>> it = mapXML.entrySet().iterator();
123                Entry<String, String> entry;
124                String xml,hashArg,hash;
125                while(it.hasNext()){
126                        entry = it.next();
127                        hashArg=entry.getKey();
128                        xml=entry.getValue();
129                        
130                        hashDir=dir.getRealResource(hashArg);
131                        if(!hashDir.isDirectory())hashDir.createDirectory(true);
132                        
133                        writeEHCacheXML(hashDir,xml);
134                        hash=MD5.getDigestAsString(xml);
135                        
136                        moveData(dir,hashArg,cacheNames,arguments);
137                        //print.e(xml);
138                        Configuration conf = ConfigurationFactory.parseConfiguration(new ByteArrayInputStream(xml.getBytes(CharsetUtil.UTF8)));
139                        conf.setName("ehcache_"+config.getId());
140                        CacheManagerAndHash m = new CacheManagerAndHash(CacheManager.newInstance(conf),hash);
141                        newManagers.put(hashDir.getAbsolutePath(), m);
142                }
143                
144                clean(dir);
145        }
146        
147        public static void flushAllCaches() {
148                String[] names;
149                Iterator<Entry<String, CacheManagerAndHash>> it = managers.entrySet().iterator();
150                Entry<String, CacheManagerAndHash> entry;
151                while(it.hasNext()){
152                        entry = it.next();
153                        CacheManager manager=entry.getValue().manager;
154                        names = manager.getCacheNames();
155                        for(int i=0;i<names.length;i++){
156                                manager.getCache(names[i]).flush();
157                        }
158                }
159        }
160        
161        private static void clean(Resource dir) {
162                Resource[] dirs = dir.listResources();
163                Resource[] children;
164                
165                for(int i=0;i<dirs.length;i++){
166                        if(dirs[i].isDirectory()){
167                                //print.out(dirs[i]+":"+pathes.contains(dirs[i].getAbsolutePath()));
168                                children=dirs[i].listResources();
169                                if(children!=null && children.length>1)continue;
170                                clean(children);
171                                dirs[i].delete();
172                        }
173                }
174        }
175
176        private static void clean(Resource[] arr) {
177                if(arr!=null)for(int i=0;i<arr.length;i++){
178                        if(arr[i].isDirectory()){
179                                clean(arr[i].listResources());
180                        }
181                        arr[i].delete();
182                }
183        }
184
185        private static void moveData(Resource dir, String hash, String[] cacheNames, Struct[] arguments) {
186                String h;
187                Resource trg = dir.getRealResource(hash);
188                deleteData(dir, cacheNames);
189                for(int i=0;i<cacheNames.length;i++){
190                        h=createHash(arguments[i]);
191                        if(h.equals(hash)){
192                                moveData(dir,cacheNames[i],trg);
193                        }
194                }
195                
196        }
197
198        private static void moveData(Resource dir, String cacheName, Resource trg) {
199                Resource[] dirs = dir.listResources();
200                Resource index,data;
201                // move 
202                for(int i=0;i<dirs.length;i++){
203                        if(!dirs[i].equals(trg) && 
204                                dirs[i].isDirectory() && 
205                                (data=dirs[i].getRealResource(cacheName+".data")).exists() && 
206                                (index=dirs[i].getRealResource(cacheName+".index")).exists() ){
207                                
208                                try {
209                                        index.moveTo(trg.getRealResource(cacheName+".index"));
210                                        data.moveTo(trg.getRealResource(cacheName+".data"));
211                                } catch (IOException e) {
212                                        e.printStackTrace();
213                                }
214                        }
215                }
216        }
217        
218        private static void deleteData(Resource dir, String[] cacheNames) {
219                Set<String> names=new HashSet<String>();
220                for(int i=0;i<cacheNames.length;i++){
221                        names.add(cacheNames[i]);
222                }
223                
224                Resource[] dirs = dir.listResources();
225                String name;
226                // move 
227                for(int i=0;i<dirs.length;i++){
228                        if(dirs[i].isDirectory()){
229                                Resource[] datas = dirs[i].listResources(new DataFiter());
230                                if(datas!=null) for(int y=0;y<datas.length;y++){
231                                        name=datas[y].getName();
232                                        name=name.substring(0,name.length()-5);
233                                        if(!names.contains(name)){
234                                                datas[y].delete();
235                                                dirs[i].getRealResource(name+".index").delete();
236                                        }
237                                                
238                                }
239                        }
240                }
241        }
242
243        private static void writeEHCacheXML(Resource hashDir, String xml) {
244                ByteArrayInputStream is = new ByteArrayInputStream(xml.getBytes(CharsetUtil.UTF8));
245                OutputStream os=null;
246                try{
247                        os = hashDir.getRealResource("ehcache.xml").getOutputStream();
248                        Util.copy(is, os);
249                }
250                catch(IOException ioe){ioe.printStackTrace();}
251                finally{
252                        Util.closeEL(os);
253                }
254        }
255
256        private static String createHash(Struct args) {
257                
258                        String dist = args.get("distributed","").toString().trim().toLowerCase();
259                        try {
260                                if(dist.equals("off")){
261                                        return MD5.getDigestAsString(dist);
262                                }
263                                else if(dist.equals("automatic")){
264                                        return MD5.getDigestAsString(
265                                                dist+
266                                                args.get("automatic_timeToLive","").toString().trim().toLowerCase()+
267                                                args.get("automatic_addional","").toString().trim().toLowerCase()+
268                                                args.get("automatic_multicastGroupPort","").toString().trim().toLowerCase()+
269                                                args.get("automatic_multicastGroupAddress","").toString().trim().toLowerCase()+
270                                                args.get("automatic_hostName","").toString().trim().toLowerCase()
271                                        );
272                                }
273                                else {
274                                         return MD5.getDigestAsString(
275                                                dist+
276                                                args.get("manual_rmiUrls","").toString().trim().toLowerCase()+
277                                                args.get("manual_addional","").toString().trim().toLowerCase()+
278                                                args.get("listener_hostName","").toString().trim().toLowerCase()+
279                                                args.get("listener_port","").toString().trim().toLowerCase()+
280                                                args.get("listener_remoteObjectPort","").toString().trim().toLowerCase()+
281                                                args.get("listener_socketTimeoutMillis","120000").toString().trim().toLowerCase()
282                                        ); 
283                                }
284                                
285                        } catch (IOException e) {
286                                e.printStackTrace();
287                                return "";
288                        }
289        }
290        private static String[] createHash(Struct[] arguments) {
291                String[] hashes=new String[arguments.length];
292                for(int i=0;i<arguments.length;i++){
293                        hashes[i]=createHash(arguments[i]);
294                }
295                return hashes;
296        }
297
298        private static String createXML(String path, String[] cacheNames,Struct[] arguments, String[] hashes, String hash) {
299                boolean isDistributed=false;
300                
301                //Cast caster = CFMLEngineFactory.getInstance().getCastUtil();
302                Struct global=null;
303                for(int i=0;i<hashes.length;i++){
304                        if(hash.equals(hashes[i])){
305                                global=arguments[i];
306                                break;
307                        }
308                }
309                
310                
311                StringBuilder xml=new StringBuilder();
312                xml.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
313                xml.append("<ehcache xsi:noNamespaceSchemaLocation=\"ehcache.xsd\">\n");
314                                
315                // disk storage
316                xml.append("<diskStore path=\"");
317                xml.append(path);
318                xml.append("\"/>\n");
319                xml.append("<cacheManagerEventListenerFactory class=\"\" properties=\"\"/>\n");
320                
321                
322                // RMI
323                // Automatic
324                if(global!=null && global.get("distributed","").equals("automatic")){
325                        // provider
326                        isDistributed=true;
327                        xml.append("<cacheManagerPeerProviderFactory \n");
328                        xml.append(" class=\"net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory\"\n ");
329                        String add = global.get("automatic_addional","").toString().trim();
330                        String hostName=global.get("automatic_hostName","").toString().trim().toLowerCase();
331                        if(!Util.isEmpty(hostName)) add+=",hostName="+hostName;
332                        if(!Util.isEmpty(add) && !add.startsWith(","))add=","+add;
333                        add=add.replace('\n', ' ');
334                        xml.append(" properties=\"peerDiscovery=automatic" +
335                                        ", multicastGroupAddress="+global.get("automatic_multicastGroupAddress","").toString().trim().toLowerCase()+
336                                        ", multicastGroupPort="+global.get("automatic_multicastGroupPort","").toString().trim().toLowerCase()+
337                                        ", timeToLive="+toTimeToLive(global.get("automatic_timeToLive","").toString().trim().toLowerCase())+
338                                        add+" \" />\n");
339                        
340                        //hostName=fully_qualified_hostname_or_ip,
341                        
342                        // listener
343                        xml.append("<cacheManagerPeerListenerFactory class=\"net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory\"/>\n");
344                        
345                }
346                // Manual
347                else if(global!=null && global.get("distributed","").equals("manual")){
348                        // provider
349                        isDistributed=true;
350                        xml.append("<cacheManagerPeerProviderFactory");
351                        xml.append(" class=\"net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory\" ");
352                        String add = global.get("manual_addional","").toString().trim();
353                        if(!Util.isEmpty(add) && !add.startsWith(","))add=","+add;
354                        add=add.replace('\n', ' ');
355                        xml.append(" properties=\"peerDiscovery=manual, rmiUrls="+global.get("manual_rmiUrls","").toString().trim().toLowerCase().replace('\n', ' ')+
356                                        add+"\"/>\n"); //propertySeparator=\",\" 
357                
358                        // listener
359                        StringBuilder sb=new StringBuilder();
360                        
361                        String hostName=global.get("listener_hostName","").toString().trim().toLowerCase();
362                        if(!Util.isEmpty(hostName)) add(sb,"hostName="+hostName);
363                        String port = global.get("listener_port","").toString().trim().toLowerCase();
364                        if(!Util.isEmpty(port)) add(sb,"port="+port);
365                        String remoteObjectPort = global.get("listener_remoteObjectPort","").toString().trim().toLowerCase();
366                        if(!Util.isEmpty(remoteObjectPort)) add(sb,"remoteObjectPort="+remoteObjectPort);
367                        String socketTimeoutMillis = global.get("listener_socketTimeoutMillis","").toString().trim().toLowerCase();
368                        if(!Util.isEmpty(socketTimeoutMillis) && !"120000".equals(socketTimeoutMillis)) 
369                                add(sb,"socketTimeoutMillis="+socketTimeoutMillis);
370                        
371                        xml.append("<cacheManagerPeerListenerFactory"); 
372                        xml.append(" class=\"net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory\""); 
373                        if(sb.length()>0)xml.append(" properties=\""+sb+"\""); 
374                        xml.append("/>\n");
375                        
376                        
377                }
378
379                
380                
381                if(isDistributed){
382                }
383                
384        
385        
386
387                
388                xml.append("<defaultCache \n");
389                xml.append("   diskPersistent=\"true\"\n");
390                xml.append("   eternal=\"false\"\n");
391                xml.append("   maxElementsInMemory=\"10000\"\n");
392                xml.append("   maxElementsOnDisk=\"10000000\"\n");
393                xml.append("   memoryStoreEvictionPolicy=\"LRU\"\n");
394                xml.append("   timeToIdleSeconds=\"86400\"\n");
395                xml.append("   timeToLiveSeconds=\"86400\"\n");
396                xml.append("   overflowToDisk=\"true\"\n");
397                xml.append("   diskSpoolBufferSizeMB=\"30\"\n");
398                xml.append("   diskExpiryThreadIntervalSeconds=\"3600\"\n");
399                xml.append(" />\n");
400                
401                // cache
402                for(int i=0;i<cacheNames.length && i<arguments.length;i++){
403                        if(hashes[i].equals(hash))createCacheXml(xml,cacheNames[i],arguments[i],isDistributed);
404                }
405                
406                
407                xml.append("</ehcache>\n");
408                return xml.toString();
409        }
410        
411        
412        
413        private static void add(StringBuilder sb,String str) {
414                if(sb.length()>0)sb.append(", ");
415                sb.append(str);
416        }
417
418        private static int toTimeToLive(String str) {
419                if(str.indexOf("host")!=-1) return 0;
420                if(str.indexOf("site")!=-1) return 1;
421                if(str.indexOf("region")!=-1) return 64;
422                if(str.indexOf("continent")!=-1) return 128;
423                return 255;     
424        }
425
426        private static void createCacheXml(StringBuilder xml, String cacheName, Struct arguments, boolean isDistributed) {
427
428                // disk Persistent
429                boolean diskPersistent=toBooleanValue(arguments.get("diskpersistent",Boolean.FALSE),DISK_PERSISTENT);
430                
431                // eternal
432                boolean eternal=toBooleanValue(arguments.get("eternal",Boolean.FALSE),ETERNAL);
433                
434                // max elements in memory
435                int maxElementsInMemory=toIntValue(arguments.get("maxelementsinmemory",new Integer(MAX_ELEMENTS_IN_MEMEORY)),MAX_ELEMENTS_IN_MEMEORY);
436                
437                // max elements on disk
438                int maxElementsOnDisk=toIntValue(arguments.get("maxelementsondisk",new Integer(MAX_ELEMENTS_ON_DISK)),MAX_ELEMENTS_ON_DISK);
439                
440                // memory eviction policy
441                String strPolicy=toString(arguments.get("memoryevictionpolicy",MEMORY_EVICTION_POLICY),MEMORY_EVICTION_POLICY);
442                String policy = "LRU";
443                if("FIFO".equalsIgnoreCase(strPolicy)) policy="FIFO";
444                else if("LFU".equalsIgnoreCase(strPolicy)) policy="LFU";
445                
446                // overflow to disk
447                boolean overflowToDisk=toBooleanValue(arguments.get("overflowtodisk",Boolean.FALSE),OVERFLOW_TO_DISK);
448                
449                // time to idle seconds
450                long timeToIdleSeconds=toLongValue(arguments.get("timeToIdleSeconds",new Long(TIME_TO_IDLE_SECONDS)),TIME_TO_IDLE_SECONDS);
451                
452                // time to live seconds
453                long timeToLiveSeconds=toLongValue(arguments.get("timeToLiveSeconds",new Long(TIME_TO_LIVE_SECONDS)),TIME_TO_LIVE_SECONDS);
454                
455        // REPLICATION
456                boolean replicatePuts=toBooleanValue(arguments.get("replicatePuts",Boolean.FALSE),REPLICATE_PUTS);
457                boolean replicatePutsViaCopy=toBooleanValue(arguments.get("replicatePutsViaCopy",Boolean.FALSE),REPLICATE_PUTS_VIA_COPY);
458                boolean replicateUpdates=toBooleanValue(arguments.get("replicateUpdates",Boolean.FALSE),REPLICATE_UPDATES);
459                boolean replicateUpdatesViaCopy=toBooleanValue(arguments.get("replicateUpdatesViaCopy",Boolean.FALSE),REPLICATE_UPDATES_VIA_COPY);
460                boolean replicateRemovals=toBooleanValue(arguments.get("replicateRemovals",Boolean.FALSE),REPLICATE_REMOVALS);
461                boolean replicateAsynchronously=toBooleanValue(arguments.get("replicateAsynchronously",Boolean.FALSE),REPLICATE_ASYNC);
462                int asynchronousReplicationInterval=toIntValue(arguments.get("asynchronousReplicationIntervalMillis",new Integer(ASYNC_REP_INTERVAL)),ASYNC_REP_INTERVAL);
463                
464                
465                
466                xml.append("<cache name=\""+cacheName+"\"\n");
467                xml.append("   diskPersistent=\""+diskPersistent+"\"\n");
468                xml.append("   eternal=\""+eternal+"\"\n");
469                xml.append("   maxElementsInMemory=\""+maxElementsInMemory+"\"\n");
470                xml.append("   maxElementsOnDisk=\""+maxElementsOnDisk+"\"\n");
471                xml.append("   memoryStoreEvictionPolicy=\""+policy+"\"\n");
472                xml.append("   timeToIdleSeconds=\""+timeToIdleSeconds+"\"\n");
473                xml.append("   timeToLiveSeconds=\""+timeToLiveSeconds+"\"\n");
474                xml.append("   overflowToDisk=\""+overflowToDisk+"\"");
475                xml.append(">\n");
476                if(isDistributed){
477                        xml.append(" <cacheEventListenerFactory \n");
478                        //xml.append(" class=\"net.sf.ehcache.distribution.RMICacheReplicatorFactory\" ");
479                        xml.append(" class=\""+LuceeRMICacheReplicatorFactory.class.getName()+"\" \n");
480                        
481                        xml.append(" properties=\"replicateAsynchronously="+replicateAsynchronously+
482                                        ", asynchronousReplicationIntervalMillis="+asynchronousReplicationInterval+
483                                        ", replicatePuts="+replicatePuts+
484                                        ", replicatePutsViaCopy="+replicatePutsViaCopy+
485                                        ", replicateUpdates="+replicateUpdates+
486                                        ", replicateUpdatesViaCopy="+replicateUpdatesViaCopy+
487                                        ", replicateRemovals="+replicateRemovals+" \"");
488                        xml.append("/>\n");
489                        
490
491                        // BootStrap
492                        if(toBooleanValue(arguments.get("bootstrapType","false"),false)){
493                                xml.append("<bootstrapCacheLoaderFactory \n");
494                                xml.append("    class=\"net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory\" \n");
495                                xml.append("    properties=\"bootstrapAsynchronously="+toBooleanValue(arguments.get("bootstrapAsynchronously","true"),true)+
496                                                ", maximumChunkSizeBytes="+toLongValue(arguments.get("maximumChunkSizeBytes","5000000"),5000000L)+"\" \n");
497                                xml.append("    propertySeparator=\",\" /> \n");
498                        }
499                
500                        
501                }
502                xml.append(" </cache>\n");
503        
504                
505        }
506
507
508
509        public void init(String cacheName, Struct arguments) {
510                init(ThreadLocalPageContext.getConfig(),cacheName, arguments);
511                
512        }
513        @Override
514        public void init(Config config,String cacheName, Struct arguments) {
515                this.classLoader=config.getClassLoader();
516                this.cacheName=cacheName;
517                
518                setClassLoader();
519                Resource hashDir = config.getConfigDir().getRealResource("ehcache").getRealResource(createHash(arguments));
520                manager =managers.get(hashDir.getAbsolutePath()).manager;
521        } 
522
523        private void setClassLoader() {
524                if(classLoader!=Thread.currentThread().getContextClassLoader())
525                        Thread.currentThread().setContextClassLoader(classLoader);
526        }
527
528        protected net.sf.ehcache.Cache getCache() {
529                setClassLoader();
530                Cache c = manager.getCache(cacheName);
531                if(c==null)
532                        throw new PageRuntimeException(new ApplicationException(ExceptionUtil.similarKeyMessage(CollectionUtil.toKeys(manager.getCacheNames(),false), cacheName, "cache name", "caches", true)));
533                return c;
534        }
535
536        @Override
537        public boolean remove(String key) {
538                try     {
539                        return getCache().remove(key);
540                }
541                catch(Throwable t){
542                ExceptionUtil.rethrowIfNecessary(t);
543                        return false;
544                }
545        }
546
547        public CacheEntry getCacheEntry(String key) throws CacheException {
548                try {
549                        misses++;
550                        Element el = getCache().get(key);
551                        if(el==null)throw new CacheException("there is no entry in cache with key ["+key+"]");
552                        hits++;
553                        misses--;
554                        return new EHCacheEntry(el);
555                }
556                catch(IllegalStateException ise) {
557                        throw new CacheException(ise.getMessage());
558                }
559                catch(net.sf.ehcache.CacheException ce) {
560                        throw new CacheException(ce.getMessage());
561                }
562        }
563
564        public CacheEntry getCacheEntry(String key, CacheEntry defaultValue) {
565                try {
566                        Element el = getCache().get(key);
567                        if(el!=null){
568                                hits++;
569                                return new EHCacheEntry(el);
570                        }
571                }
572                catch(Throwable t) {
573                ExceptionUtil.rethrowIfNecessary(t);
574                        misses++;
575                }
576                return defaultValue;
577        }
578
579        @Override
580        public Object getValue(String key) throws CacheException {
581                try {
582                        misses++;
583                        Element el = getCache().get(key);
584                        if(el==null)throw new CacheException("there is no entry in cache with key ["+key+"]");
585                        misses--;
586                        hits++;
587                        return el.getObjectValue();
588                }
589                catch(IllegalStateException ise) {
590                        throw new CacheException(ise.getMessage());
591                }
592                catch(net.sf.ehcache.CacheException ce) {
593                        throw new CacheException(ce.getMessage());
594                }
595        }
596
597        @Override
598        public Object getValue(String key, Object defaultValue) {
599                try {
600                        Element el = getCache().get(key);
601                        if(el!=null){
602                                hits++;
603                                return el.getObjectValue();
604                        }
605                }
606                catch(Throwable t) {
607                ExceptionUtil.rethrowIfNecessary(t);
608                        misses++;
609                }
610                return defaultValue;
611        }
612
613        @Override
614        public long hitCount() {
615                return hits;
616        }
617
618        @Override
619        public long missCount() {
620                return misses;
621        }
622
623        public void remove() {
624                setClassLoader();
625                CacheManager singletonManager = CacheManager.getInstance();
626                if(singletonManager.cacheExists(cacheName))
627                        singletonManager.removeCache(cacheName);
628                
629        }
630
631        
632        
633
634        private static boolean toBooleanValue(Object o, boolean defaultValue) {
635                if(o instanceof Boolean) return ((Boolean)o).booleanValue();
636        else if(o instanceof Number) return (((Number)o).doubleValue())!=0;
637        else if(o instanceof String) {
638                String str = o.toString().trim().toLowerCase();
639            if(str.equals("yes") || str.equals("on") || str.equals("true")) return true;
640            else if(str.equals("no") || str.equals("false") || str.equals("off")) return false;
641        }
642        return defaultValue;
643        }
644
645        private static String toString(Object o, String defaultValue) {
646                if(o instanceof String)return o.toString();
647                return defaultValue;
648        }
649
650        private static int toIntValue(Object o, int defaultValue) {
651                if(o instanceof Number) return ((Number)o).intValue();
652                try{
653                return Integer.parseInt(o.toString());
654                }
655                catch(Throwable t){
656                ExceptionUtil.rethrowIfNecessary(t);
657                        return defaultValue;
658                }
659        }
660
661        private static long toLongValue(Object o, long defaultValue) {
662                if(o instanceof Number) return ((Number)o).longValue();
663                try{
664                        return Long.parseLong(o.toString());
665                }
666                catch(Throwable t){
667                ExceptionUtil.rethrowIfNecessary(t);
668                        return defaultValue;
669                }
670        }
671
672        @Override
673        public int clear() throws IOException {
674                int size=getCache().getSize();
675                getCache().removeAll();
676                return size;
677        }
678        
679
680}class CacheManagerAndHash {
681
682                CacheManager manager;
683                String hash;
684
685                public CacheManagerAndHash(CacheManager manager, String hash) {
686                        this.manager=manager;
687                        
688                        this.hash=hash;
689                }
690                
691        }
692
693class DataFiter implements ResourceNameFilter {
694
695        @Override
696        public boolean accept(Resource parent, String name) {
697                return name.endsWith(".data");
698        }
699
700}