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