blob: f89acf2360cca236721332af23c675627aff0c0f [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2002-2004 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26/*
27 */
28
29package java.io;
30
31import java.util.Iterator;
32import java.util.Map;
33import java.util.LinkedHashMap;
34import java.util.Set;
35
36class ExpiringCache {
37 private long millisUntilExpiration;
38 private Map map;
39 // Clear out old entries every few queries
40 private int queryCount;
41 private int queryOverflow = 300;
42 private int MAX_ENTRIES = 200;
43
44 static class Entry {
45 private long timestamp;
46 private String val;
47
48 Entry(long timestamp, String val) {
49 this.timestamp = timestamp;
50 this.val = val;
51 }
52
53 long timestamp() { return timestamp; }
54 void setTimestamp(long timestamp) { this.timestamp = timestamp; }
55
56 String val() { return val; }
57 void setVal(String val) { this.val = val; }
58 }
59
60 ExpiringCache() {
61 this(30000);
62 }
63
64 ExpiringCache(long millisUntilExpiration) {
65 this.millisUntilExpiration = millisUntilExpiration;
66 map = new LinkedHashMap() {
67 protected boolean removeEldestEntry(Map.Entry eldest) {
68 return size() > MAX_ENTRIES;
69 }
70 };
71 }
72
73 synchronized String get(String key) {
74 if (++queryCount >= queryOverflow) {
75 cleanup();
76 }
77 Entry entry = entryFor(key);
78 if (entry != null) {
79 return entry.val();
80 }
81 return null;
82 }
83
84 synchronized void put(String key, String val) {
85 if (++queryCount >= queryOverflow) {
86 cleanup();
87 }
88 Entry entry = entryFor(key);
89 if (entry != null) {
90 entry.setTimestamp(System.currentTimeMillis());
91 entry.setVal(val);
92 } else {
93 map.put(key, new Entry(System.currentTimeMillis(), val));
94 }
95 }
96
97 synchronized void clear() {
98 map.clear();
99 }
100
101 private Entry entryFor(String key) {
102 Entry entry = (Entry) map.get(key);
103 if (entry != null) {
104 long delta = System.currentTimeMillis() - entry.timestamp();
105 if (delta < 0 || delta >= millisUntilExpiration) {
106 map.remove(key);
107 entry = null;
108 }
109 }
110 return entry;
111 }
112
113 private void cleanup() {
114 Set keySet = map.keySet();
115 // Avoid ConcurrentModificationExceptions
116 String[] keys = new String[keySet.size()];
117 int i = 0;
118 for (Iterator iter = keySet.iterator(); iter.hasNext(); ) {
119 String key = (String) iter.next();
120 keys[i++] = key;
121 }
122 for (int j = 0; j < keys.length; j++) {
123 entryFor(keys[j]);
124 }
125 queryCount = 0;
126 }
127}