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 }