001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.cache.memory;
016    
017    import com.liferay.portal.kernel.cache.AbstractPortalCache;
018    import com.liferay.portal.kernel.cache.PortalCacheManager;
019    
020    import java.io.Serializable;
021    
022    import java.util.ArrayList;
023    import java.util.List;
024    import java.util.concurrent.ConcurrentHashMap;
025    import java.util.concurrent.ConcurrentMap;
026    
027    /**
028     * @author Brian Wing Shun Chan
029     * @author Edward Han
030     * @author Shuyang Zhou
031     */
032    public class MemoryPortalCache<K extends Serializable, V>
033            extends AbstractPortalCache<K, V> {
034    
035            public MemoryPortalCache(
036                    PortalCacheManager<K, V> portalCacheManager, String name,
037                    int initialCapacity) {
038    
039                    super(portalCacheManager);
040    
041                    _name = name;
042    
043                    _concurrentMap = new ConcurrentHashMap<K, V>(initialCapacity);
044            }
045    
046            public void destroy() {
047                    removeAll();
048    
049                    _concurrentMap = null;
050                    _name = null;
051            }
052    
053            @Override
054            public List<K> getKeys() {
055                    List<K> keys = new ArrayList<K>();
056    
057                    for (K key : _concurrentMap.keySet()) {
058                            keys.add(key);
059                    }
060    
061                    return keys;
062            }
063    
064            @Override
065            public String getName() {
066                    return _name;
067            }
068    
069            @Override
070            public void removeAll() {
071                    _concurrentMap.clear();
072    
073                    aggregatedCacheListener.notifyRemoveAll(this);
074            }
075    
076            @Override
077            protected V doGet(K key) {
078                    return _concurrentMap.get(key);
079            }
080    
081            @Override
082            protected void doPut(K key, V value, int timeToLive) {
083                    V oldValue = _concurrentMap.put(key, value);
084    
085                    if (oldValue != null) {
086                            aggregatedCacheListener.notifyEntryUpdated(
087                                    this, key, value, timeToLive);
088                    }
089                    else {
090                            aggregatedCacheListener.notifyEntryPut(
091                                    this, key, value, timeToLive);
092                    }
093            }
094    
095            @Override
096            protected V doPutIfAbsent(K key, V value, int timeToLive) {
097                    V oldValue = _concurrentMap.putIfAbsent(key, value);
098    
099                    if (oldValue == null) {
100                            aggregatedCacheListener.notifyEntryPut(
101                                    this, key, value, timeToLive);
102                    }
103    
104                    return oldValue;
105            }
106    
107            @Override
108            protected void doRemove(K key) {
109                    V value = _concurrentMap.remove(key);
110    
111                    if (value != null) {
112                            aggregatedCacheListener.notifyEntryRemoved(
113                                    this, key, value, DEFAULT_TIME_TO_LIVE);
114                    }
115            }
116    
117            @Override
118            protected boolean doRemove(K key, V value) {
119                    boolean removed = _concurrentMap.remove(key, value);
120    
121                    if (removed) {
122                            aggregatedCacheListener.notifyEntryRemoved(
123                                    this, key, value, DEFAULT_TIME_TO_LIVE);
124                    }
125    
126                    return removed;
127            }
128    
129            @Override
130            protected V doReplace(K key, V value, int timeToLive) {
131                    V oldValue = _concurrentMap.replace(key, value);
132    
133                    if (oldValue != null) {
134                            aggregatedCacheListener.notifyEntryUpdated(
135                                    this, key, value, timeToLive);
136                    }
137    
138                    return oldValue;
139            }
140    
141            @Override
142            protected boolean doReplace(K key, V oldValue, V newValue, int timeToLive) {
143                    boolean replaced = _concurrentMap.replace(key, oldValue, newValue);
144    
145                    if (replaced) {
146                            aggregatedCacheListener.notifyEntryUpdated(
147                                    this, key, newValue, timeToLive);
148                    }
149    
150                    return replaced;
151            }
152    
153            private ConcurrentMap<K, V> _concurrentMap;
154            private String _name;
155    
156    }