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 = portalCache.get(cacheKey);
120
121 if (result == null) {
122 result = StringPool.BLANK;
123
124 portalCache.put(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 = portalCache.get(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 portalCache.put(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 portalCache.put(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 portalCache.remove(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 return CACHE_NAME.concat(StringPool.PERIOD).concat(className);
291 }
292
293 private String _encodeLocalCacheKey(
294 Class<?> classObj, Serializable primaryKeyObj) {
295
296 return classObj.getName().concat(StringPool.PERIOD).concat(
297 primaryKeyObj.toString());
298 }
299
300 private PortalCache _getPortalCache(String className) {
301 String groupKey = _encodeGroupKey(className);
302
303 PortalCache portalCache = _portalCaches.get(groupKey);
304
305 if (portalCache == null) {
306 portalCache = _multiVMPool.getCache(
307 groupKey, PropsValues.VALUE_OBJECT_ENTITY_BLOCKING_CACHE);
308
309 _portalCaches.put(groupKey, portalCache);
310 }
311
312 return portalCache;
313 }
314
315 private Object _objectToResult(Object result) {
316 if (result instanceof String) {
317 return null;
318 }
319 else {
320 result = ((BaseModel<?>)result).clone();
321
322 BaseModel<?> model = (BaseModel<?>)result;
323
324 model.setCachedModel(true);
325
326 return model;
327 }
328 }
329
330 private static Log _log = LogFactoryUtil.getLog(EntityCacheImpl.class);
331
332 private static ThreadLocal<LRUMap> _localCache;
333 private static boolean _localCacheAvailable;
334 private static ThreadLocal<Boolean> _localCacheEnabled =
335 new InitialThreadLocal<Boolean>(Boolean.FALSE);
336
337 static {
338 if (PropsValues.VALUE_OBJECT_ENTITY_THREAD_LOCAL_CACHE_MAX_SIZE > 0) {
339 _localCache = new InitialThreadLocal<LRUMap>(new LRUMap(
340 PropsValues.VALUE_OBJECT_ENTITY_THREAD_LOCAL_CACHE_MAX_SIZE));
341 _localCacheAvailable = true;
342 }
343 }
344
345 private MultiVMPool _multiVMPool;
346 private Map<String, PortalCache> _portalCaches =
347 new ConcurrentHashMap<String, PortalCache>();
348
349 }