1. /*
  2. * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
  3. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  4. */
  5. /*
  6. * @(#)ExpiringCache.java 1.3 03/01/23
  7. */
  8. package java.io;
  9. import java.util.Iterator;
  10. import java.util.Map;
  11. import java.util.HashMap;
  12. import java.util.Set;
  13. class ExpiringCache {
  14. private long millisUntilExpiration;
  15. private Map map;
  16. // Clear out old entries every few queries
  17. private int queryCount;
  18. private int queryOverflow = 300;
  19. static class Entry {
  20. private long timestamp;
  21. private String val;
  22. Entry(long timestamp, String val) {
  23. this.timestamp = timestamp;
  24. this.val = val;
  25. }
  26. long timestamp() { return timestamp; }
  27. void setTimestamp(long timestamp) { this.timestamp = timestamp; }
  28. String val() { return val; }
  29. void setVal(String val) { this.val = val; }
  30. }
  31. ExpiringCache() {
  32. this(30000);
  33. }
  34. ExpiringCache(long millisUntilExpiration) {
  35. this.millisUntilExpiration = millisUntilExpiration;
  36. map = new HashMap();
  37. }
  38. synchronized String get(String key) {
  39. if (++queryCount >= queryOverflow) {
  40. cleanup();
  41. }
  42. Entry entry = entryFor(key);
  43. if (entry != null) {
  44. return entry.val();
  45. }
  46. return null;
  47. }
  48. synchronized void put(String key, String val) {
  49. if (++queryCount >= queryOverflow) {
  50. cleanup();
  51. }
  52. Entry entry = entryFor(key);
  53. if (entry != null) {
  54. entry.setTimestamp(System.currentTimeMillis());
  55. entry.setVal(val);
  56. } else {
  57. map.put(key, new Entry(System.currentTimeMillis(), val));
  58. }
  59. }
  60. synchronized void clear() {
  61. map.clear();
  62. }
  63. private Entry entryFor(String key) {
  64. Entry entry = (Entry) map.get(key);
  65. if (entry != null) {
  66. long delta = System.currentTimeMillis() - entry.timestamp();
  67. if (delta < 0 || delta >= millisUntilExpiration) {
  68. map.remove(key);
  69. entry = null;
  70. }
  71. }
  72. return entry;
  73. }
  74. private void cleanup() {
  75. Set keySet = map.keySet();
  76. // Avoid ConcurrentModificationExceptions
  77. String[] keys = new String[keySet.size()];
  78. int i = 0;
  79. for (Iterator iter = keySet.iterator(); iter.hasNext(); ) {
  80. String key = (String) iter.next();
  81. keys[i++] = key;
  82. }
  83. for (int j = 0; j < keys.length; j++) {
  84. entryFor(keys[j]);
  85. }
  86. queryCount = 0;
  87. }
  88. }