001
014
015 package com.liferay.portal.kernel.util;
016
017 import com.liferay.portal.kernel.memory.EqualityWeakReference;
018 import com.liferay.portal.kernel.memory.FinalizeAction;
019 import com.liferay.portal.kernel.memory.FinalizeManager;
020
021 import java.io.Serializable;
022
023 import java.lang.ref.Reference;
024
025 import java.util.AbstractCollection;
026 import java.util.AbstractSet;
027 import java.util.ArrayList;
028 import java.util.Collection;
029 import java.util.Iterator;
030 import java.util.List;
031 import java.util.Map;
032 import java.util.Set;
033 import java.util.concurrent.ConcurrentHashMap;
034 import java.util.concurrent.ConcurrentMap;
035
036
039 public class WeakValueConcurrentHashMap<K, V>
040 implements ConcurrentMap<K, V>, Serializable {
041
042 public WeakValueConcurrentHashMap() {
043 _map = new ConcurrentHashMap<K, Reference<V>>();
044 }
045
046 public WeakValueConcurrentHashMap(int initialCapacity) {
047 _map = new ConcurrentHashMap<K, Reference<V>>(initialCapacity);
048 }
049
050 public WeakValueConcurrentHashMap(
051 int initialCapacity, float loadFactor, int concurrencyLevel) {
052 _map = new ConcurrentHashMap<K, Reference<V>>(
053 initialCapacity, loadFactor, concurrencyLevel);
054 }
055
056 public WeakValueConcurrentHashMap(Map<? extends K, ? extends V> map) {
057 _map = new ConcurrentHashMap<K, Reference<V>>();
058
059 putAll(map);
060 }
061
062 public void clear() {
063 _map.clear();
064 }
065
066 public boolean containsKey(Object key) {
067 return _map.containsKey(key);
068 }
069
070 public boolean containsValue(Object value) {
071 return _map.containsValue(new EqualityWeakReference<V>((V)value));
072 }
073
074 public Set<Entry<K, V>> entrySet() {
075 if (_entrySet == null) {
076 _entrySet = new UnwrapEntrySet();
077 }
078
079 return _entrySet;
080 }
081
082 public V get(Object key) {
083 Reference<V> valueReference = _map.get(key);
084
085 if (valueReference != null) {
086 return valueReference.get();
087 }
088
089 return null;
090 }
091
092 public boolean isEmpty() {
093 return _map.isEmpty();
094 }
095
096 public Set<K> keySet() {
097 return _map.keySet();
098 }
099
100 public V put(K key, V value) {
101 Reference<V> valueReference = wrapValue(key, value);
102
103 valueReference = _map.putIfAbsent(key, valueReference);
104
105 if (valueReference != null) {
106 return valueReference.get();
107 }
108
109 return null;
110 }
111
112 public final void putAll(Map<? extends K, ? extends V> map) {
113 for (Map.Entry<? extends K, ? extends V> entry : map.entrySet()) {
114 K key = entry.getKey();
115 V value = entry.getValue();
116
117 Reference<V> valueReference = wrapValue(key, value);
118
119 _map.put(key, valueReference);
120 }
121 }
122
123 public V putIfAbsent(K key, V value) {
124 Reference<V> valueReference = wrapValue(key, value);
125
126 valueReference = _map.putIfAbsent(key, valueReference);
127
128 if (valueReference != null) {
129 return valueReference.get();
130 }
131
132 return null;
133 }
134
135 public V remove(Object key) {
136 Reference<V> valueReference = _map.remove(key);
137
138 if (valueReference != null) {
139 return valueReference.get();
140 }
141
142 return null;
143 }
144
145 public boolean remove(Object key, Object value) {
146 Reference<V> valueReference = wrapValue(key, value);
147
148 return _map.remove(key, valueReference);
149 }
150
151 public V replace(K key, V value) {
152 Reference<V> valueReference = wrapValue(key, value);
153
154 valueReference = _map.replace(key, valueReference);
155
156 if (valueReference != null) {
157 return valueReference.get();
158 }
159
160 return null;
161 }
162
163 public boolean replace(K key, V oldValue, V newValue) {
164 Reference<V> oldValueReference = wrapValue(key, oldValue);
165 Reference<V> newValueReference = wrapValue(key, newValue);
166
167 return _map.replace(key, oldValueReference, newValueReference);
168 }
169
170 public int size() {
171 return _map.size();
172 }
173
174 public Collection<V> values() {
175 if (_values == null) {
176 _values = new UnwrapValues();
177 }
178
179 return _values;
180 }
181
182 protected Reference<V> wrapValue(Object key, Object value) {
183 return FinalizeManager.register(
184 (V)value, new RemoveEntryFinalizeAction((K) key));
185 }
186
187 private transient Set<Map.Entry<K, V>> _entrySet;
188 private final ConcurrentMap<K, Reference<V>> _map;
189 private transient Collection<V> _values;
190
191 private class RemoveEntryFinalizeAction implements FinalizeAction {
192
193 public RemoveEntryFinalizeAction(K key) {
194 _key = key;
195 }
196
197 public void doFinalize() {
198 remove(_key);
199 }
200
201 private final K _key;
202
203 }
204
205 private class UnwrapEntry implements Map.Entry<K, V> {
206
207 public UnwrapEntry(Entry<K, Reference<V>> entry) {
208 _entry = entry;
209 }
210
211 public K getKey() {
212 return _entry.getKey();
213 }
214
215 public V getValue() {
216 Reference<V> valueReference = _entry.getValue();
217
218 if (valueReference != null) {
219 return valueReference.get();
220 }
221
222 return null;
223 }
224
225 public V setValue(V value) {
226 return WeakValueConcurrentHashMap.this.put(_entry.getKey(), value);
227 }
228
229 private Map.Entry<K, Reference<V>> _entry;
230
231 }
232
233 private class UnwrapEntryIterator implements Iterator<Map.Entry<K, V>> {
234
235 public UnwrapEntryIterator() {
236 _iterator = _map.entrySet().iterator();
237 }
238
239 public boolean hasNext() {
240 return _iterator.hasNext();
241 }
242
243 public Entry<K, V> next() {
244 return new UnwrapEntry(_iterator.next());
245 }
246
247 public void remove() {
248 _iterator.remove();
249 }
250
251 private Iterator<Map.Entry<K, Reference<V>>> _iterator;
252
253 }
254
255 private class UnwrapEntrySet extends AbstractSet<Map.Entry<K, V>> {
256
257 @Override
258 public void clear() {
259 WeakValueConcurrentHashMap.this.clear();
260 }
261
262 @Override
263 public boolean contains(Object obj) {
264 if (!(obj instanceof Map.Entry<?, ?>)) {
265 return false;
266 }
267
268 Map.Entry<K, V> entry = (Map.Entry<K, V>)obj;
269
270 V value = WeakValueConcurrentHashMap.this.get(entry.getKey());
271
272 if ((value != null) && value.equals(entry.getValue())) {
273 return true;
274 }
275 else {
276 return false;
277 }
278 }
279
280 @Override
281 public Iterator<Map.Entry<K, V>> iterator() {
282 return new UnwrapEntryIterator();
283 }
284
285 @Override
286 public boolean remove(Object obj) {
287 if (!(obj instanceof Map.Entry<?, ?>)) {
288 return false;
289 }
290
291 Map.Entry<K, V> entry = (Map.Entry<K, V>)obj;
292
293 return WeakValueConcurrentHashMap.this.remove(
294 entry.getKey(), entry.getValue());
295 }
296
297 @Override
298 public int size() {
299 return WeakValueConcurrentHashMap.this.size();
300 }
301
302 @Override
303 public Object[] toArray() {
304 List<Map.Entry<K, V>> list = new ArrayList<Map.Entry<K, V>>(size());
305
306 Iterator<Map.Entry<K, V>> iterator = iterator();
307
308 while (iterator.hasNext()) {
309 list.add(iterator.next());
310 }
311
312 return list.toArray();
313 }
314
315 @Override
316 public <T> T[] toArray(T[] array) {
317 List<Map.Entry<K, V>> list = new ArrayList<Map.Entry<K, V>>(size());
318
319 Iterator<Map.Entry<K, V>> iterator = iterator();
320
321 while (iterator.hasNext()) {
322 list.add(iterator.next());
323 }
324
325 return list.toArray(array);
326 }
327
328 }
329
330 private class UnwrapValueIterator implements Iterator<V> {
331
332 public UnwrapValueIterator() {
333 _iterator = _map.values().iterator();
334 }
335
336 public boolean hasNext() {
337 return _iterator.hasNext();
338 }
339
340 public V next() {
341 Reference<V> valueReference = _iterator.next();
342
343 if (valueReference != null) {
344 return valueReference.get();
345 }
346
347 return null;
348 }
349
350 public void remove() {
351 _iterator.remove();
352 }
353
354 private Iterator<Reference<V>> _iterator;
355
356 }
357
358 private class UnwrapValues extends AbstractCollection<V> {
359
360 @Override
361 public void clear() {
362 WeakValueConcurrentHashMap.this.clear();
363 }
364
365 @Override
366 public boolean contains(Object obj) {
367 return WeakValueConcurrentHashMap.this.containsValue(obj);
368 }
369
370 @Override
371 public Iterator<V> iterator() {
372 return new UnwrapValueIterator();
373 }
374
375 @Override
376 public int size() {
377 return WeakValueConcurrentHashMap.this.size();
378 }
379
380 @Override
381 public Object[] toArray() {
382 List<V> list = new ArrayList<V>();
383
384 Iterator<V> iterator = iterator();
385
386 while (iterator.hasNext()) {
387 list.add(iterator.next());
388 }
389
390 return list.toArray();
391 }
392
393 @Override
394 public <T> T[] toArray(T[] a) {
395 List<V> list = new ArrayList<V>();
396
397 Iterator<V> iterator = iterator();
398
399 while (iterator.hasNext()) {
400 list.add(iterator.next());
401 }
402
403 return list.toArray(a);
404 }
405
406 }
407
408 }