1 /*
2 * Copyright (c) 1998-2005 The Jgroup Team.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16 *
17 */
18 package jgroup.util;
19
20 import java.util.Collections;
21 import java.util.HashMap;
22 import java.util.Iterator;
23 import java.util.Map;
24
25 import org.apache.log4j.Logger;
26
27 /**
28 * Implementation of a map with limited access times to a key/value pair. When
29 * an entry is inserted in the map, you must specify the number of times the
30 * entry can be retrieved before it is inaccessible/removed.<p>
31 *
32 * This map can be useful when caching objects, and you need a way to remove old
33 * items from the cache.
34 *
35 * @author Rohnny Moland
36 */
37 public class CacheMap<K, V>
38 extends HashMap<K, V>
39 {
40
41 ////////////////////////////////////////////////////////////////////////////////////////////
42 // Logger
43 ////////////////////////////////////////////////////////////////////////////////////////////
44
45 private static final Logger log = Logger.getLogger(CacheMap.class);
46
47
48 ////////////////////////////////////////////////////////////////////////////////////////////
49 // Fields
50 ////////////////////////////////////////////////////////////////////////////////////////////
51
52 /** The serial version uid */
53 private static final long serialVersionUID = 8045886013359387147L;
54
55 /** Map holding access times for the cache */
56 private Map<Object, Integer> accessTimes = Collections
57 .synchronizedMap(new HashMap<Object, Integer>());
58
59
60 ////////////////////////////////////////////////////////////////////////////////////////////
61 // Constructor and instance methods
62 ////////////////////////////////////////////////////////////////////////////////////////////
63
64 public CacheMap()
65 {
66 super();
67 }
68
69
70 /**
71 * Returns the value of the given key, if key is accessible. If not,
72 * return null.
73 */
74 @Override
75 public V get(Object key)
76 {
77 if (key == null)
78 return null;
79 Integer a = (Integer) accessTimes.get(key);
80 if (a == null)
81 return null;
82
83 int access = a.intValue() - 1;
84 if (access > 1) {
85 if (log.isDebugEnabled())
86 log.debug("Access value=" + access);
87 accessTimes.put(key, new Integer(access));
88 return super.get(key);
89 } else {
90 accessTimes.remove(key);
91 return super.remove(key);
92 }
93 }
94
95
96 /**
97 * Insert a key/value in a <code>HashMap</code>, and set the number of
98 * times it can be accessed.
99 */
100 public void put(K key, V value, int maxAccesses)
101 {
102 if (maxAccesses > 1) {
103 accessTimes.put(key, new Integer(maxAccesses));
104 super.put(key, value);
105 }
106 }
107
108
109 @Override
110 public V put(K key, V value)
111 {
112 throw new UnsupportedOperationException("put(K,V) is not supported by CacheMap");
113 }
114
115
116 @Override
117 public void putAll(Map<? extends K, ? extends V> m)
118 {
119 throw new UnsupportedOperationException("putAll(..) is not supported by CacheMap");
120 }
121
122
123 /**
124 * Clear the map.
125 */
126 @Override
127 public void clear()
128 {
129 super.clear();
130 accessTimes.clear();
131 }
132
133
134 /**
135 * Returns the size of cache map
136 */
137 @Override
138 public int size()
139 {
140 return super.size();
141 }
142
143
144 @Override
145 public String toString()
146 {
147 StringBuffer buf = new StringBuffer();
148 buf.append("CacheMap.accessTimes");
149 buf.append("\n");
150 synchronized (this) {
151 for (Iterator iter = accessTimes.entrySet().iterator(); iter.hasNext();) {
152 Map.Entry entry = (Map.Entry) iter.next();
153 buf.append("[");
154 buf.append(entry.getKey());
155 buf.append("]: ");
156 buf.append(entry.getValue());
157 buf.append("\n");
158 }
159 return buf.toString();
160 }
161 }
162
163 } // END CacheMap