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