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