1
14
15 package com.liferay.portal.dao.orm.common;
16
17 import com.liferay.portal.kernel.cache.CacheRegistry;
18 import com.liferay.portal.kernel.cache.CacheRegistryItem;
19 import com.liferay.portal.kernel.cache.MultiVMPool;
20 import com.liferay.portal.kernel.cache.PortalCache;
21 import com.liferay.portal.kernel.cache.key.CacheKeyGenerator;
22 import com.liferay.portal.kernel.cache.key.CacheKeyGeneratorUtil;
23 import com.liferay.portal.kernel.dao.orm.EntityCache;
24 import com.liferay.portal.kernel.dao.orm.Session;
25 import com.liferay.portal.kernel.dao.orm.SessionFactory;
26 import com.liferay.portal.kernel.log.Log;
27 import com.liferay.portal.kernel.log.LogFactoryUtil;
28 import com.liferay.portal.kernel.util.AutoResetThreadLocal;
29 import com.liferay.portal.kernel.util.StringPool;
30 import com.liferay.portal.model.BaseModel;
31 import com.liferay.portal.util.PropsValues;
32
33 import java.io.Serializable;
34
35 import java.util.Map;
36 import java.util.concurrent.ConcurrentHashMap;
37 import java.util.concurrent.ConcurrentMap;
38
39 import org.apache.commons.collections.map.LRUMap;
40
41
46 public class EntityCacheImpl implements CacheRegistryItem, EntityCache {
47
48 public static final String CACHE_NAME = EntityCache.class.getName();
49
50 public void afterPropertiesSet() {
51 CacheRegistry.register(this);
52 }
53
54 public void clearCache() {
55 clearLocalCache();
56
57 for (PortalCache portalCache : _portalCaches.values()) {
58 portalCache.removeAll();
59 }
60 }
61
62 public void clearCache(String className) {
63 clearLocalCache();
64
65 PortalCache portalCache = _getPortalCache(className, false);
66
67 if (portalCache != null) {
68 portalCache.removeAll();
69 }
70 }
71
72 public void clearLocalCache() {
73 if (_localCacheAvailable) {
74 _localCache.remove();
75 }
76 }
77
78 public String getRegistryName() {
79 return CACHE_NAME;
80 }
81
82 public Object getResult(
83 boolean entityCacheEnabled, Class<?> classObj,
84 Serializable primaryKeyObj, SessionFactory sessionFactory) {
85
86 if (!PropsValues.VALUE_OBJECT_ENTITY_CACHE_ENABLED ||
87 !entityCacheEnabled || !CacheRegistry.isActive()) {
88
89 return null;
90 }
91
92 Object result = null;
93
94 Map<String, Object> localCache = null;
95
96 String localCacheKey = null;
97
98 if (_localCacheAvailable) {
99 localCache = _localCache.get();
100
101 localCacheKey = _encodeLocalCacheKey(classObj, primaryKeyObj);
102
103 result = localCache.get(localCacheKey);
104 }
105
106 if (result == null) {
107 PortalCache portalCache = _getPortalCache(classObj.getName(), true);
108
109 String cacheKey = _encodeCacheKey(primaryKeyObj);
110
111 result = portalCache.get(cacheKey);
112
113 if (result == null) {
114 result = StringPool.BLANK;
115
116 portalCache.put(cacheKey, result);
117 }
118
119 if (_localCacheAvailable) {
120 localCache.put(localCacheKey, result);
121 }
122 }
123
124 if (result != null) {
125 result = _objectToResult(result);
126 }
127
128 return result;
129 }
130
131 public void invalidate() {
132 clearCache();
133 }
134
135 public Object loadResult(
136 boolean entityCacheEnabled, Class<?> classObj,
137 Serializable primaryKeyObj, SessionFactory sessionFactory) {
138
139 if (!PropsValues.VALUE_OBJECT_ENTITY_CACHE_ENABLED ||
140 !entityCacheEnabled || !CacheRegistry.isActive()) {
141
142 Session session = null;
143
144 try {
145 session = sessionFactory.openSession();
146
147 return session.load(classObj, primaryKeyObj);
148 }
149 finally {
150 sessionFactory.closeSession(session);
151 }
152 }
153
154 Object result = null;
155
156 Map<String, Object> localCache = null;
157
158 String localCacheKey = null;
159
160 if (_localCacheAvailable) {
161 localCache = _localCache.get();
162
163 localCacheKey = _encodeLocalCacheKey(classObj, primaryKeyObj);
164
165 result = localCache.get(localCacheKey);
166 }
167
168 if (result == null) {
169 PortalCache portalCache = _getPortalCache(classObj.getName(), true);
170
171 String cacheKey = _encodeCacheKey(primaryKeyObj);
172
173 result = portalCache.get(cacheKey);
174
175 if (result == null) {
176 if (_log.isDebugEnabled()) {
177 _log.debug(
178 "Load " + classObj + " " + primaryKeyObj +
179 " from session");
180 }
181
182 Session session = null;
183
184 try {
185 session = sessionFactory.openSession();
186
187 result = session.load(classObj, primaryKeyObj);
188 }
189 finally {
190 if (result == null) {
191 result = StringPool.BLANK;
192 }
193 else {
194 result = _objectToResult(result);
195 }
196
197 portalCache.put(cacheKey, result);
198
199 sessionFactory.closeSession(session);
200 }
201 }
202
203 if (_localCacheAvailable) {
204 localCache.put(localCacheKey, result);
205 }
206 }
207
208 result = _objectToResult(result);
209
210 return result;
211 }
212
213 public void putResult(
214 boolean entityCacheEnabled, Class<?> classObj,
215 Serializable primaryKeyObj, Object result) {
216
217 if (!PropsValues.VALUE_OBJECT_ENTITY_CACHE_ENABLED ||
218 !entityCacheEnabled || !CacheRegistry.isActive() ||
219 (result == null)) {
220
221 return;
222 }
223
224 result = _objectToResult(result);
225
226 if (_localCacheAvailable) {
227 Map<String, Object> localCache = _localCache.get();
228
229 String localCacheKey = _encodeLocalCacheKey(
230 classObj, primaryKeyObj);
231
232 localCache.put(localCacheKey, result);
233 }
234
235 PortalCache portalCache = _getPortalCache(classObj.getName(), true);
236
237 String cacheKey = _encodeCacheKey(primaryKeyObj);
238
239 portalCache.put(cacheKey, result);
240 }
241
242 public void removeResult(
243 boolean entityCacheEnabled, Class<?> classObj,
244 Serializable primaryKeyObj) {
245
246 if (!PropsValues.VALUE_OBJECT_ENTITY_CACHE_ENABLED ||
247 !entityCacheEnabled || !CacheRegistry.isActive()) {
248
249 return;
250 }
251
252 if (_localCacheAvailable) {
253 Map<String, Object> localCache = _localCache.get();
254
255 String localCacheKey = _encodeLocalCacheKey(
256 classObj, primaryKeyObj);
257
258 localCache.remove(localCacheKey);
259 }
260
261 PortalCache portalCache = _getPortalCache(classObj.getName(), true);
262
263 String cacheKey = _encodeCacheKey(primaryKeyObj);
264
265 portalCache.remove(cacheKey);
266 }
267
268 public void setMultiVMPool(MultiVMPool multiVMPool) {
269 _multiVMPool = multiVMPool;
270 }
271
272 private String _encodeCacheKey(Serializable primaryKeyObj) {
273 CacheKeyGenerator cacheKeyGenerator =
274 CacheKeyGeneratorUtil.getCacheKeyGenerator(CACHE_NAME);
275
276 return cacheKeyGenerator.getCacheKey(primaryKeyObj.toString());
277 }
278
279 private String _encodeLocalCacheKey(
280 Class<?> classObj, Serializable primaryKeyObj) {
281
282 CacheKeyGenerator cacheKeyGenerator =
283 CacheKeyGeneratorUtil.getCacheKeyGenerator(CACHE_NAME);
284
285 cacheKeyGenerator.append(classObj.getName());
286 cacheKeyGenerator.append(primaryKeyObj.toString());
287
288 return cacheKeyGenerator.finish();
289 }
290
291 private PortalCache _getPortalCache(
292 String className, boolean createIfAbsent) {
293 String groupKey = _GROUP_KEY_PREFIX.concat(className);
294
295 PortalCache portalCache = _portalCaches.get(groupKey);
296
297 if ((portalCache == null) && createIfAbsent) {
298 portalCache = _multiVMPool.getCache(
299 groupKey, PropsValues.VALUE_OBJECT_ENTITY_BLOCKING_CACHE);
300
301 PortalCache previousPortalCache = _portalCaches.putIfAbsent(
302 groupKey, portalCache);
303
304 if (previousPortalCache != null) {
305 portalCache = previousPortalCache;
306 }
307
308 portalCache.setDebug(true);
309 }
310
311 return portalCache;
312 }
313
314 private Object _objectToResult(Object result) {
315 if (result instanceof String) {
316 return null;
317 }
318 else {
319 result = ((BaseModel<?>)result).clone();
320
321 BaseModel<?> model = (BaseModel<?>)result;
322
323 model.setCachedModel(true);
324
325 return model;
326 }
327 }
328
329 private static Log _log = LogFactoryUtil.getLog(EntityCacheImpl.class);
330
331 private static final String _GROUP_KEY_PREFIX = CACHE_NAME.concat(
332 StringPool.PERIOD);
333
334 private static ThreadLocal<LRUMap> _localCache;
335 private static boolean _localCacheAvailable;
336
337 static {
338 if (PropsValues.VALUE_OBJECT_ENTITY_THREAD_LOCAL_CACHE_MAX_SIZE > 0) {
339 _localCache = new AutoResetThreadLocal<LRUMap>(
340 EntityCacheImpl.class + "._localCache",
341 new LRUMap(
342 PropsValues.
343 VALUE_OBJECT_ENTITY_THREAD_LOCAL_CACHE_MAX_SIZE));
344 _localCacheAvailable = true;
345 }
346 }
347
348 private MultiVMPool _multiVMPool;
349 private ConcurrentMap<String, PortalCache> _portalCaches =
350 new ConcurrentHashMap<String, PortalCache>();
351
352 }