001    /**
002     * Copyright (c) 2000-2012 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.transactional;
016    
017    import com.liferay.portal.kernel.cache.PortalCache;
018    import com.liferay.portal.kernel.util.InitialThreadLocal;
019    import com.liferay.portal.util.PropsValues;
020    
021    import java.io.Serializable;
022    
023    import java.util.ArrayList;
024    import java.util.HashMap;
025    import java.util.List;
026    import java.util.Map;
027    
028    /**
029     * @author Shuyang Zhou
030     */
031    public class TransactionalPortalCacheHelper {
032    
033            public static void begin() {
034                    if (!PropsValues.TRANSACTIONAL_CACHE_ENABLED) {
035                            return;
036                    }
037    
038                    _pushPortalCacheMap();
039            }
040    
041            public static void commit() {
042                    if (!PropsValues.TRANSACTIONAL_CACHE_ENABLED) {
043                            return;
044                    }
045    
046                    PortalCacheMap portalCacheMap = _popPortalCacheMap();
047    
048                    for (Map.Entry
049                                    <PortalCache<? extends Serializable, ?>,
050                                            Map<? extends Serializable, ?>> portalCacheMapEntry :
051                                    portalCacheMap.entrySet()) {
052    
053                            PortalCache<Serializable, Object> portalCache =
054                                    (PortalCache<Serializable, Object>)portalCacheMapEntry.getKey();
055    
056                            Map<? extends Serializable, ?> uncommittedMap =
057                                    portalCacheMapEntry.getValue();
058    
059                            for (Map.Entry<? extends Serializable, ?> uncommittedMapEntry :
060                                            uncommittedMap.entrySet()) {
061    
062                                    portalCache.put(
063                                            uncommittedMapEntry.getKey(),
064                                            uncommittedMapEntry.getValue());
065                            }
066                    }
067    
068                    portalCacheMap.clear();
069            }
070    
071            public static boolean isEnabled() {
072                    if (!PropsValues.TRANSACTIONAL_CACHE_ENABLED) {
073                            return false;
074                    }
075    
076                    List<PortalCacheMap> portalCacheMaps =
077                            _portalCacheMapsThreadLocal.get();
078    
079                    return !portalCacheMaps.isEmpty();
080            }
081    
082            public static void rollback() {
083                    if (!PropsValues.TRANSACTIONAL_CACHE_ENABLED) {
084                            return;
085                    }
086    
087                    PortalCacheMap portalCacheMap = _popPortalCacheMap();
088    
089                    portalCacheMap.clear();
090            }
091    
092            protected static <K extends Serializable, V> V get(
093                    PortalCache<K, V> portalCache, K key) {
094    
095                    PortalCacheMap portalCacheMap = _peekPortalCacheMap();
096    
097                    Map<? extends Serializable, ?> uncommittedMap = portalCacheMap.get(
098                            portalCache);
099    
100                    if (uncommittedMap == null) {
101                            return null;
102                    }
103    
104                    return (V)uncommittedMap.get(key);
105            }
106    
107            protected static <K extends Serializable, V> void put(
108                    PortalCache<K, V> portalCache, K key, V value) {
109    
110                    PortalCacheMap portalCacheMap = _peekPortalCacheMap();
111    
112                    Map<Serializable, Object> uncommittedMap =
113                            (Map<Serializable, Object>)portalCacheMap.get(portalCache);
114    
115                    if (uncommittedMap == null) {
116                            uncommittedMap = new HashMap<Serializable, Object>();
117    
118                            portalCacheMap.put(portalCache, uncommittedMap);
119                    }
120    
121                    uncommittedMap.put(key, value);
122            }
123    
124            protected static <K extends Serializable, V> void remove(
125                    PortalCache<K, V> portalCache, K key) {
126    
127                    PortalCacheMap portalCacheMap = _peekPortalCacheMap();
128    
129                    Map<? extends Serializable, ?> uncommittedMap = portalCacheMap.get(
130                            portalCache);
131    
132                    if (uncommittedMap != null) {
133                            uncommittedMap.remove(key);
134                    }
135            }
136    
137            protected static <K extends Serializable, V> void removeAll(
138                    PortalCache<K, V> portalCache) {
139    
140                    PortalCacheMap portalCacheMap = _peekPortalCacheMap();
141    
142                    Map<? extends Serializable, ?> uncommittedMap = portalCacheMap.get(
143                            portalCache);
144    
145                    if (uncommittedMap != null) {
146                            uncommittedMap.clear();
147                    }
148            }
149    
150            private static PortalCacheMap _peekPortalCacheMap() {
151                    List<PortalCacheMap> portalCacheMaps =
152                            _portalCacheMapsThreadLocal.get();
153    
154                    return portalCacheMaps.get(portalCacheMaps.size() - 1);
155            }
156    
157            private static PortalCacheMap _popPortalCacheMap() {
158                    List<PortalCacheMap> portalCacheMaps =
159                            _portalCacheMapsThreadLocal.get();
160    
161                    return portalCacheMaps.remove(portalCacheMaps.size() - 1);
162            }
163    
164            private static void _pushPortalCacheMap() {
165                    List<PortalCacheMap> portalCacheMaps =
166                            _portalCacheMapsThreadLocal.get();
167    
168                    portalCacheMaps.add(new PortalCacheMap());
169            }
170    
171            private static ThreadLocal<List<PortalCacheMap>>
172                    _portalCacheMapsThreadLocal =
173                            new InitialThreadLocal<List<PortalCacheMap>>(
174                                    TransactionalPortalCacheHelper.class.getName() +
175                                            "._portalCacheMapsThreadLocal",
176                                    new ArrayList<PortalCacheMap>());
177    
178            private static class PortalCacheMap
179                    extends HashMap
180                            <PortalCache<? extends Serializable, ?>,
181                                    Map<? extends Serializable, ?>> {
182            }
183    
184    }