1
22
23 package com.liferay.portal.spring.hibernate;
24
25 import com.liferay.portal.kernel.cache.CacheKVP;
26 import com.liferay.portal.kernel.cache.CacheRegistry;
27 import com.liferay.portal.kernel.cache.CacheRegistryItem;
28 import com.liferay.portal.kernel.cache.MultiVMPoolUtil;
29 import com.liferay.portal.kernel.cache.PortalCache;
30 import com.liferay.portal.kernel.util.ArrayUtil;
31 import com.liferay.portal.kernel.util.GetterUtil;
32 import com.liferay.portal.kernel.util.StringMaker;
33 import com.liferay.portal.kernel.util.StringPool;
34 import com.liferay.portal.model.BaseModel;
35 import com.liferay.portal.util.PropsUtil;
36
37 import java.io.Serializable;
38
39 import java.util.ArrayList;
40 import java.util.List;
41 import java.util.Map;
42 import java.util.Set;
43 import java.util.concurrent.ConcurrentHashMap;
44
45 import org.hibernate.Session;
46 import org.hibernate.SessionFactory;
47
48
54 public class FinderCache implements CacheRegistryItem {
55
56 public static final boolean CACHE_ENABLED = GetterUtil.getBoolean(
57 PropsUtil.get(PropsUtil.VALUE_OBJECT_FINDER_CACHE_ENABLED), true);
58
59 public static final String CACHE_NAME = FinderCache.class.getName();
60
61 public static void clearCache() {
62 _instance._clearCache();
63 }
64
65 public static void clearCache(String className) {
66 _instance._clearCache(className);
67 }
68
69 public static Object getResult(
70 String className, String methodName, String[] params, Object[] args) {
71
72 return _instance._getResult(className, methodName, params, args);
73 }
74
75 public static Object getResult(
76 String className, String methodName, String[] params, Object[] args,
77 SessionFactory sessionFactory) {
78
79 return _instance._getResult(
80 className, methodName, params, args, sessionFactory);
81 }
82
83 public static Object getResult(
84 String sql, String[] classNames, String methodName, String[] params,
85 Object[] args) {
86
87 return _instance._getResult(sql, classNames, methodName, params, args);
88 }
89
90 public static Object getResult(
91 String sql, String[] classNames, String methodName, String[] params,
92 Object[] args, SessionFactory sessionFactory) {
93
94 return _instance._getResult(
95 sql, classNames, methodName, params, args, sessionFactory);
96 }
97
98 public static void putResult(
99 boolean classNameCacheEnabled, String className, String methodName,
100 String[] params, Object[] args, Object result) {
101
102 _instance._putResult(
103 classNameCacheEnabled, className, methodName, params, args, result);
104 }
105
106 public static void putResult(
107 String sql, boolean[] classNamesCacheEnabled, String[] classNames,
108 String methodName, String[] params, Object[] args, Object result) {
109
110 _instance._putResult(
111 sql, classNamesCacheEnabled, classNames, methodName, params, args,
112 result);
113 }
114
115 public void invalidate() {
116 _clearCache();
117 }
118
119 private FinderCache() {
120 CacheRegistry.register(this);
121 }
122
123 private void _clearCache() {
124 _cache.removeAll();
125 }
126
127 private void _clearCache(String className) {
128 String groupKey = _encodeGroupKey(className);
129
130 MultiVMPoolUtil.clearGroup(_groups, groupKey, _cache);
131 }
132
133 private Object _getResult(
134 String className, String methodName, String[] params, Object[] args) {
135
136 return _getResult(className, methodName, params, args, null);
137 }
138
139 private Object _getResult(
140 String className, String methodName, String[] params, Object[] args,
141 SessionFactory sessionFactory) {
142
143 String key = _encodeKey(className, methodName, params, args);
144
145 Object primaryKey = MultiVMPoolUtil.get(_cache, key);
146
147 if (primaryKey != null) {
148 Session session = null;
149
150 try {
151 session = HibernateUtil.openSession(sessionFactory);
152
153 return _primaryKeyToResult(session, primaryKey);
154 }
155 finally {
156 HibernateUtil.closeSession(session);
157 }
158 }
159 else {
160 return null;
161 }
162 }
163
164 private Object _getResult(
165 String sql, String[] classNames, String methodName, String[] params,
166 Object[] args) {
167
168 return _getResult(sql, classNames, methodName, params, args, null);
169 }
170
171 private Object _getResult(
172 String sql, String[] classNames, String methodName, String[] params,
173 Object[] args, SessionFactory sessionFactory) {
174
175 String key = _encodeKey(sql, methodName, params, args);
176
177 Object primaryKey = MultiVMPoolUtil.get(_cache, key);
178
179 if (primaryKey != null) {
180 Session session = null;
181
182 try {
183 session = HibernateUtil.openSession(sessionFactory);
184
185 return _primaryKeyToResult(session, primaryKey);
186 }
187 finally {
188 HibernateUtil.closeSession(session);
189 }
190 }
191 else {
192 return null;
193 }
194 }
195
196 private void _putResult(
197 boolean classNameCacheEnabled, String className, String methodName,
198 String[] params, Object[] args, Object result) {
199
200 if (classNameCacheEnabled && CACHE_ENABLED &&
201 CacheRegistry.isActive() && (result != null)) {
202
203 String key = _encodeKey(className, methodName, params, args);
204
205 String groupKey = _encodeGroupKey(className);
206
207 MultiVMPoolUtil.put(
208 _cache, key, _groups, groupKey, _resultToPrimaryKey(result));
209 }
210 }
211
212 private void _putResult(
213 String sql, boolean[] classNamesCacheEnabled, String[] classNames,
214 String methodName, String[] params, Object[] args, Object result) {
215
216 if (ArrayUtil.contains(classNamesCacheEnabled, false)) {
217 return;
218 }
219
220 if (CACHE_ENABLED && CacheRegistry.isActive() && (result != null)) {
221 String key = _encodeKey(sql, methodName, params, args);
222
223 for (String className : classNames) {
224 String groupKey = _encodeGroupKey(className);
225
226 MultiVMPoolUtil.updateGroup(_groups, groupKey, key);
227 }
228
229 MultiVMPoolUtil.put(_cache, key, _resultToPrimaryKey(result));
230 }
231 }
232
233 private String _encodeGroupKey(String className) {
234 StringMaker sm = new StringMaker();
235
236 sm.append(CACHE_NAME);
237 sm.append(StringPool.POUND);
238 sm.append(className);
239
240 return sm.toString();
241 }
242
243 private String _encodeKey(
244 String className, String methodName, String[] params, Object[] args) {
245
246 StringMaker sm = new StringMaker();
247
248 sm.append(CACHE_NAME);
249 sm.append(StringPool.POUND);
250 sm.append(className);
251 sm.append(StringPool.POUND);
252 sm.append(methodName);
253 sm.append(_PARAMS_SEPARATOR);
254
255 for (String param : params) {
256 sm.append(StringPool.POUND);
257 sm.append(param);
258 }
259
260 sm.append(_ARGS_SEPARATOR);
261
262 for (Object arg : args) {
263 sm.append(StringPool.POUND);
264 sm.append(String.valueOf(arg));
265 }
266
267 return sm.toString();
268 }
269
270 private Object _primaryKeyToResult(
271 Session session, Object primaryKey) {
272
273 if (primaryKey instanceof CacheKVP) {
274 CacheKVP cacheKVP = (CacheKVP)primaryKey;
275
276 Class<?> modelClass = cacheKVP.getModelClass();
277 Serializable primaryKeyObj = cacheKVP.getPrimaryKeyObj();
278
279 return session.load(modelClass, primaryKeyObj);
280 }
281 else if (primaryKey instanceof List) {
282 List<Object> cachedList = (List<Object>)primaryKey;
283
284 List<Object> list = new ArrayList<Object>(cachedList.size());
285
286 for (Object curPrimaryKey : cachedList) {
287 Object result = _primaryKeyToResult(session, curPrimaryKey);
288
289 list.add(result);
290 }
291
292 return list;
293 }
294 else {
295 return primaryKey;
296 }
297 }
298
299 private Object _resultToPrimaryKey(Object result) {
300 if (result instanceof BaseModel) {
301 BaseModel model = (BaseModel)result;
302
303 Class<?> modelClass = model.getClass();
304 Serializable primaryKeyObj = model.getPrimaryKeyObj();
305
306 return new CacheKVP(modelClass, primaryKeyObj);
307 }
308 else if (result instanceof List) {
309 List<Object> list = (List<Object>)result;
310
311 List<Object> cachedList = new ArrayList<Object>(list.size());
312
313 for (Object curResult : list) {
314 Object primaryKey = _resultToPrimaryKey(curResult);
315
316 cachedList.add(primaryKey);
317 }
318
319 return cachedList;
320 }
321 else {
322 return result;
323 }
324 }
325
326 private static final String _ARGS_SEPARATOR = "_ARGS_SEPARATOR_";
327
328 private static final String _PARAMS_SEPARATOR = "_PARAMS_SEPARATOR_";
329
330 private static FinderCache _instance = new FinderCache();
331
332 private PortalCache _cache = MultiVMPoolUtil.getCache(CACHE_NAME);
333
334 private Map<String, Set<String>> _groups =
335 new ConcurrentHashMap<String, Set<String>>();
336
337 }