1
22
23 package com.liferay.portal.dao.orm.common;
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
51 public class EntityCacheImpl implements CacheRegistryItem, EntityCache {
52
53 public static final String CACHE_NAME = EntityCache.class.getName();
54
55 public void afterPropertiesSet() {
56 CacheRegistry.register(this);
57 }
58
59 public void clearCache() {
60 clearLocalCache();
61
62 PortalCache[] portalCaches = _portalCaches.values().toArray(
63 new PortalCache[_portalCaches.size()]);
64
65 for (PortalCache portalCache : portalCaches) {
66 portalCache.removeAll();
67 }
68 }
69
70 public void clearCache(String className) {
71 clearLocalCache();
72
73 PortalCache portalCache = _getPortalCache(className);
74
75 portalCache.removeAll();
76 }
77
78 public void clearLocalCache() {
79 if (_localCacheEnabled.get().booleanValue()) {
80 Map<String, Object> localCache = _localCache.get();
81
82 localCache.clear();
83 }
84 }
85
86 public String getRegistryName() {
87 return CACHE_NAME;
88 }
89
90 public Object getResult(
91 boolean entityCacheEnabled, Class<?> classObj,
92 Serializable primaryKeyObj, SessionFactory sessionFactory) {
93
94 if (!PropsValues.VALUE_OBJECT_ENTITY_CACHE_ENABLED ||
95 !entityCacheEnabled || !CacheRegistry.isActive()) {
96
97 return null;
98 }
99
100 Object result = null;
101
102 Map<String, Object> localCache = null;
103
104 String localCacheKey = null;
105
106 if (_localCacheEnabled.get().booleanValue()) {
107 localCache = _localCache.get();
108
109 localCacheKey = _encodeLocalCacheKey(classObj, primaryKeyObj);
110
111 result = localCache.get(localCacheKey);
112 }
113
114 if (result == null) {
115 PortalCache portalCache = _getPortalCache(classObj.getName());
116
117 String cacheKey = _encodeCacheKey(primaryKeyObj);
118
119 result = _multiVMPool.get(portalCache, cacheKey);
120
121 if (result == null) {
122 result = StringPool.BLANK;
123
124 _multiVMPool.put(portalCache, cacheKey, result);
125 }
126
127 if (_localCacheEnabled.get().booleanValue()) {
128 localCache.put(localCacheKey, result);
129 }
130 }
131
132 if (result != null) {
133 result = _objectToResult(result);
134 }
135
136 return result;
137 }
138
139 public void invalidate() {
140 clearCache();
141 }
142
143 public Object loadResult(
144 boolean entityCacheEnabled, Class<?> classObj,
145 Serializable primaryKeyObj, SessionFactory sessionFactory) {
146
147 if (!PropsValues.VALUE_OBJECT_ENTITY_CACHE_ENABLED ||
148 !entityCacheEnabled || !CacheRegistry.isActive()) {
149
150 Session session = null;
151
152 try {
153 session = sessionFactory.openSession();
154
155 return session.load(classObj, primaryKeyObj);
156 }
157 finally {
158 sessionFactory.closeSession(session);
159 }
160 }
161
162 Object result = null;
163
164 Map<String, Object> localCache = null;
165
166 String localCacheKey = null;
167
168 if (_localCacheEnabled.get().booleanValue()) {
169 localCache = _localCache.get();
170
171 localCacheKey = _encodeLocalCacheKey(classObj, primaryKeyObj);
172
173 result = localCache.get(localCacheKey);
174 }
175
176 if (result == null) {
177 PortalCache portalCache = _getPortalCache(classObj.getName());
178
179 String cacheKey = _encodeCacheKey(primaryKeyObj);
180
181 result = _multiVMPool.get(portalCache, cacheKey);
182
183 if (result == null) {
184 if (_log.isDebugEnabled()) {
185 _log.debug(
186 "Load " + classObj + " " + primaryKeyObj +
187 " from session");
188 }
189
190 Session session = null;
191
192 try {
193 session = sessionFactory.openSession();
194
195 result = session.load(classObj, primaryKeyObj);
196 }
197 finally {
198 if (result == null) {
199 result = StringPool.BLANK;
200 }
201
202 result = _objectToResult(result);
203
204 _multiVMPool.put(portalCache, cacheKey, result);
205
206 sessionFactory.closeSession(session);
207 }
208 }
209
210 if (_localCacheEnabled.get().booleanValue()) {
211 localCache.put(localCacheKey, result);
212 }
213 }
214
215 result = _objectToResult(result);
216
217 return result;
218 }
219
220 public void putResult(
221 boolean entityCacheEnabled, Class<?> classObj,
222 Serializable primaryKeyObj, Object result) {
223
224 if (!PropsValues.VALUE_OBJECT_ENTITY_CACHE_ENABLED ||
225 !entityCacheEnabled || !CacheRegistry.isActive() ||
226 (result == null)) {
227
228 return;
229 }
230
231 result = _objectToResult(result);
232
233 if (_localCacheEnabled.get().booleanValue()) {
234 Map<String, Object> localCache = _localCache.get();
235
236 String localCacheKey = _encodeLocalCacheKey(
237 classObj, primaryKeyObj);
238
239 localCache.put(localCacheKey, result);
240 }
241
242 PortalCache portalCache = _getPortalCache(classObj.getName());
243
244 String cacheKey = _encodeCacheKey(primaryKeyObj);
245
246 _multiVMPool.put(portalCache, cacheKey, result);
247 }
248
249 public void removeResult(
250 boolean entityCacheEnabled, Class<?> classObj,
251 Serializable primaryKeyObj) {
252
253 if (!PropsValues.VALUE_OBJECT_ENTITY_CACHE_ENABLED ||
254 !entityCacheEnabled || !CacheRegistry.isActive()) {
255
256 return;
257 }
258
259 if (_localCacheEnabled.get().booleanValue()) {
260 Map<String, Object> localCache = _localCache.get();
261
262 String localCacheKey = _encodeLocalCacheKey(
263 classObj, primaryKeyObj);
264
265 localCache.remove(localCacheKey);
266 }
267
268 PortalCache portalCache = _getPortalCache(classObj.getName());
269
270 String cacheKey = _encodeCacheKey(primaryKeyObj);
271
272 _multiVMPool.remove(portalCache, cacheKey);
273 }
274
275 public void setLocalCacheEnabled(boolean localCacheEnabled) {
276 if (_localCacheAvailable) {
277 _localCacheEnabled.set(Boolean.valueOf(localCacheEnabled));
278 }
279 }
280
281 public void setMultiVMPool(MultiVMPool multiVMPool) {
282 _multiVMPool = multiVMPool;
283 }
284
285 private String _encodeCacheKey(Serializable primaryKeyObj) {
286 return String.valueOf(primaryKeyObj);
287 }
288
289 private String _encodeGroupKey(String className) {
290 StringBuilder sb = new StringBuilder();
291
292 sb.append(CACHE_NAME);
293 sb.append(StringPool.PERIOD);
294 sb.append(className);
295
296 return sb.toString();
297 }
298
299 private String _encodeLocalCacheKey(
300 Class<?> classObj, Serializable primaryKeyObj) {
301
302 StringBuilder sb = new StringBuilder();
303
304 sb.append(classObj.getName());
305 sb.append(StringPool.PERIOD);
306 sb.append(primaryKeyObj);
307
308 return sb.toString();
309 }
310
311 private PortalCache _getPortalCache(String className) {
312 String groupKey = _encodeGroupKey(className);
313
314 PortalCache portalCache = _portalCaches.get(groupKey);
315
316 if (portalCache == null) {
317 portalCache = _multiVMPool.getCache(
318 groupKey, PropsValues.VALUE_OBJECT_ENTITY_BLOCKING_CACHE);
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 }