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