001
014
015 package com.liferay.portal.security.permission;
016
017 import com.liferay.portal.kernel.cache.MultiVMPoolUtil;
018 import com.liferay.portal.kernel.cache.PortalCache;
019 import com.liferay.portal.kernel.cache.index.IndexEncoder;
020 import com.liferay.portal.kernel.cache.index.PortalCacheIndexer;
021 import com.liferay.portal.kernel.cluster.ClusterExecutorUtil;
022 import com.liferay.portal.kernel.cluster.ClusterInvokeThreadLocal;
023 import com.liferay.portal.kernel.cluster.ClusterRequest;
024 import com.liferay.portal.kernel.exception.SystemException;
025 import com.liferay.portal.kernel.lar.ExportImportThreadLocal;
026 import com.liferay.portal.kernel.log.Log;
027 import com.liferay.portal.kernel.log.LogFactoryUtil;
028 import com.liferay.portal.kernel.util.AutoResetThreadLocal;
029 import com.liferay.portal.kernel.util.HashUtil;
030 import com.liferay.portal.kernel.util.MethodHandler;
031 import com.liferay.portal.kernel.util.MethodKey;
032 import com.liferay.portal.kernel.util.StringBundler;
033 import com.liferay.portal.kernel.util.StringPool;
034 import com.liferay.portal.kernel.util.Validator;
035 import com.liferay.portal.model.ResourceConstants;
036 import com.liferay.portal.model.Role;
037 import com.liferay.portal.util.PropsValues;
038
039 import java.io.Serializable;
040
041 import java.util.Map;
042
043 import org.apache.commons.collections.map.LRUMap;
044
045
052 public class PermissionCacheUtil {
053
054 public static final String PERMISSION_CACHE_NAME =
055 PermissionCacheUtil.class.getName() + "_PERMISSION";
056
057 public static final String PERMISSION_CHECKER_BAG_CACHE_NAME =
058 PermissionCacheUtil.class.getName() + "_PERMISSION_CHECKER_BAG";
059
060 public static final String RESOURCE_BLOCK_IDS_BAG_CACHE_NAME =
061 PermissionCacheUtil.class.getName() + "_RESOURCE_BLOCK_IDS_BAG";
062
063 public static final String USER_PERMISSION_CHECKER_BAG_CACHE_NAME =
064 PermissionCacheUtil.class.getName() + "_USER_PERMISSION_CHECKER_BAG";
065
066 public static final String USER_ROLE_CACHE_NAME =
067 PermissionCacheUtil.class.getName() + "_USER_ROLE";
068
069 public static void clearCache() {
070 if (ExportImportThreadLocal.isImportInProcess()) {
071 return;
072 }
073
074 clearLocalCache();
075
076 _permissionCheckerBagPortalCache.removeAll();
077 _permissionPortalCache.removeAll();
078 _resourceBlockIdsBagCache.removeAll();
079 _userPermissionCheckerBagPortalCache.removeAll();
080 _userRolePortalCache.removeAll();
081 }
082
083 public static void clearLocalCache() {
084 if (_localCacheAvailable) {
085 Map<Serializable, Object> localCache = _localCache.get();
086
087 localCache.clear();
088 }
089 }
090
091 public static void clearCache(long... userIds) {
092 if (ExportImportThreadLocal.isImportInProcess()) {
093 return;
094 }
095
096 clearLocalCache();
097
098 for (long userId : userIds) {
099 _userPermissionCheckerBagPortalCache.remove(userId);
100
101 _permissionCheckerBagPortalCacheIndexer.removeKeys(userId);
102 _userRolePortalCacheIndexer.removeKeys(userId);
103 }
104
105 _permissionPortalCache.removeAll();
106 _resourceBlockIdsBagCache.removeAll();
107
108 _sendClearCacheClusterMessage(_clearCacheMethodKey, userIds);
109 }
110
111 public static void clearResourceBlockCache(
112 long companyId, long groupId, String name) {
113
114 if (ExportImportThreadLocal.isImportInProcess() ||
115 !PermissionThreadLocal.isFlushResourceBlockEnabled(
116 companyId, groupId, name)) {
117
118 return;
119 }
120
121 clearLocalCache();
122
123 _resourceBlockIdsBagCacheIndexer.removeKeys(
124 ResourceBlockIdsBagKeyIndexEncoder.encode(
125 companyId, groupId, name));
126
127 _sendClearCacheClusterMessage(
128 _clearResourceBlockCacheMethodKey, companyId, groupId, name);
129 }
130
131 public static void clearResourceCache() {
132 if (!ExportImportThreadLocal.isImportInProcess()) {
133 clearLocalCache();
134
135 _resourceBlockIdsBagCache.removeAll();
136 _permissionPortalCache.removeAll();
137 }
138 }
139
140 public static void clearResourcePermissionCache(
141 int scope, String name, String primKey) {
142
143 if (ExportImportThreadLocal.isImportInProcess() ||
144 !PermissionThreadLocal.isFlushResourcePermissionEnabled(
145 name, primKey)) {
146
147 return;
148 }
149
150 clearLocalCache();
151
152 if (scope == ResourceConstants.SCOPE_INDIVIDUAL) {
153 _permissionPortalCacheNamePrimKeyIndexer.removeKeys(
154 PermissionKeyNamePrimKeyIndexEncoder.encode(name, primKey));
155
156 _sendClearCacheClusterMessage(
157 _clearResourcePermissionCacheMethodKey, scope, name, primKey);
158 }
159 else if (scope == ResourceConstants.SCOPE_GROUP) {
160 _permissionPortalCacheGroupIdIndexer.removeKeys(
161 Long.valueOf(primKey));
162
163 _sendClearCacheClusterMessage(
164 _clearResourcePermissionCacheMethodKey, scope, name, primKey);
165 }
166 else {
167 _permissionPortalCache.removeAll();
168 }
169 }
170
171 public static PermissionCheckerBag getBag(long userId, long groupId) {
172 BagKey bagKey = new BagKey(userId, groupId);
173
174 return get(bagKey, _permissionCheckerBagPortalCache);
175 }
176
177 public static Boolean getPermission(
178 long userId, boolean signedIn, long groupId, String name,
179 String primKey, String actionId) {
180
181 PermissionKey permissionKey = new PermissionKey(
182 userId, signedIn, groupId, name, primKey, actionId);
183
184 return get(permissionKey, _permissionPortalCache);
185 }
186
187 public static ResourceBlockIdsBag getResourceBlockIdsBag(
188 long companyId, long groupId, long userId, String name) {
189
190 ResourceBlockIdsBagKey resourceBlockIdsBagKey =
191 new ResourceBlockIdsBagKey(companyId, groupId, userId, name);
192
193 return get(resourceBlockIdsBagKey, _resourceBlockIdsBagCache);
194 }
195
196 public static UserPermissionCheckerBag getUserBag(long userId) {
197 return get(userId, _userPermissionCheckerBagPortalCache);
198 }
199
200 public static Boolean getUserRole(long userId, Role role) {
201 UserRoleKey userRoleKey = new UserRoleKey(userId, role.getRoleId());
202
203 Boolean userRole = _userRolePortalCache.get(userRoleKey);
204
205 if (userRole != null) {
206 return userRole;
207 }
208
209 return null;
210 }
211
212 public static void putBag(
213 long userId, long groupId, PermissionCheckerBag bag) {
214
215 if (bag == null) {
216 return;
217 }
218
219 BagKey bagKey = new BagKey(userId, groupId);
220
221 put(bagKey, bag, _permissionCheckerBagPortalCache);
222 }
223
224 public static void putPermission(
225 long userId, boolean signedIn, long groupId, String name,
226 String primKey, String actionId, Boolean value) {
227
228 PermissionKey permissionKey = new PermissionKey(
229 userId, signedIn, groupId, name, primKey, actionId);
230
231 put(permissionKey, value, _permissionPortalCache);
232 }
233
234 public static void putResourceBlockIdsBag(
235 long companyId, long groupId, long userId, String name,
236 ResourceBlockIdsBag resourceBlockIdsBag) {
237
238 if (resourceBlockIdsBag == null) {
239 return;
240 }
241
242 ResourceBlockIdsBagKey resourceBlockIdsBagKey =
243 new ResourceBlockIdsBagKey(companyId, groupId, userId, name);
244
245 put(
246 resourceBlockIdsBagKey, resourceBlockIdsBag,
247 _resourceBlockIdsBagCache);
248 }
249
250 public static void putUserBag(
251 long userId, UserPermissionCheckerBag userPermissionCheckerBag) {
252
253 put(
254 userId, userPermissionCheckerBag,
255 _userPermissionCheckerBagPortalCache);
256 }
257
258 protected static
259 <K extends Serializable, V, C extends PortalCache<K, V>> V get(
260 K key, C portalCache) {
261
262 V value = null;
263
264 if (_localCacheAvailable) {
265 Map<K, V> localCache = _localCache.get();
266
267 value = localCache.get(key);
268 }
269
270 if (value == null) {
271 value = portalCache.get(key);
272 }
273
274 return value;
275 }
276
277 protected static
278 <K extends Serializable, V, C extends PortalCache<K, V>> void put(
279 K key, V value, C portalCache) {
280
281 if (_localCacheAvailable) {
282 Map<K, V> localCache = _localCache.get();
283
284 localCache.put(key, value);
285 }
286
287 portalCache.put(key, value);
288 }
289
290 public static void putUserRole(long userId, Role role, Boolean value) {
291 if (value == null) {
292 return;
293 }
294
295 UserRoleKey userRoleKey = new UserRoleKey(userId, role.getRoleId());
296
297 _userRolePortalCache.put(userRoleKey, value);
298 }
299
300 private static void _sendClearCacheClusterMessage(
301 MethodKey methodKey, Object... arguments) {
302
303 if (!ClusterInvokeThreadLocal.isEnabled()) {
304 return;
305 }
306
307 ClusterRequest clusterRequest = ClusterRequest.createMulticastRequest(
308 new MethodHandler(methodKey, arguments), true);
309
310 clusterRequest.setFireAndForget(true);
311
312 try {
313 ClusterExecutorUtil.execute(clusterRequest);
314 }
315 catch (SystemException se) {
316 _log.error(se, se);
317 }
318 }
319
320 private static final MethodKey _clearCacheMethodKey = new MethodKey(
321 PermissionCacheUtil.class, "clearCache", long[].class);
322 private static final MethodKey _clearResourceBlockCacheMethodKey =
323 new MethodKey(
324 PermissionCacheUtil.class, "clearResourceBlockCache", long.class,
325 long.class, String.class);
326 private static final MethodKey _clearResourcePermissionCacheMethodKey =
327 new MethodKey(
328 PermissionCacheUtil.class, "clearResourcePermissionCache",
329 int.class, String.class, String.class);
330 private static final PortalCache<BagKey, PermissionCheckerBag>
331 _permissionCheckerBagPortalCache = MultiVMPoolUtil.getCache(
332 PERMISSION_CHECKER_BAG_CACHE_NAME,
333 PropsValues.PERMISSIONS_OBJECT_BLOCKING_CACHE);
334 private static final PortalCacheIndexer<Long, BagKey, PermissionCheckerBag>
335 _permissionCheckerBagPortalCacheIndexer =
336 new PortalCacheIndexer<Long, BagKey, PermissionCheckerBag>(
337 new BagKeyIndexEncoder(), _permissionCheckerBagPortalCache);
338 private static final PortalCache<PermissionKey, Boolean>
339 _permissionPortalCache = MultiVMPoolUtil.getCache(
340 PERMISSION_CACHE_NAME,
341 PropsValues.PERMISSIONS_OBJECT_BLOCKING_CACHE);
342 private static final PortalCacheIndexer<Long, PermissionKey, Boolean>
343 _permissionPortalCacheGroupIdIndexer =
344 new PortalCacheIndexer<Long, PermissionKey, Boolean>(
345 new PermissionKeyGroupIdIndexEncoder(), _permissionPortalCache);
346 private static final PortalCacheIndexer<String, PermissionKey, Boolean>
347 _permissionPortalCacheNamePrimKeyIndexer =
348 new PortalCacheIndexer<String, PermissionKey, Boolean>(
349 new PermissionKeyNamePrimKeyIndexEncoder(),
350 _permissionPortalCache);
351 private static final
352 PortalCache<ResourceBlockIdsBagKey, ResourceBlockIdsBag>
353 _resourceBlockIdsBagCache = MultiVMPoolUtil.getCache(
354 RESOURCE_BLOCK_IDS_BAG_CACHE_NAME,
355 PropsValues.PERMISSIONS_OBJECT_BLOCKING_CACHE);
356 private static final PortalCacheIndexer
357 <String, ResourceBlockIdsBagKey, ResourceBlockIdsBag>
358 _resourceBlockIdsBagCacheIndexer = new PortalCacheIndexer
359 <String, ResourceBlockIdsBagKey, ResourceBlockIdsBag>(
360 new ResourceBlockIdsBagKeyIndexEncoder(),
361 _resourceBlockIdsBagCache);
362 private static final PortalCache<Long, UserPermissionCheckerBag>
363 _userPermissionCheckerBagPortalCache = MultiVMPoolUtil.getCache(
364 USER_PERMISSION_CHECKER_BAG_CACHE_NAME,
365 PropsValues.PERMISSIONS_OBJECT_BLOCKING_CACHE);
366 private static final PortalCache<UserRoleKey, Boolean>
367 _userRolePortalCache = MultiVMPoolUtil.getCache(
368 USER_ROLE_CACHE_NAME,
369 PropsValues.PERMISSIONS_OBJECT_BLOCKING_CACHE);
370 private static final PortalCacheIndexer<Long, UserRoleKey, Boolean>
371 _userRolePortalCacheIndexer =
372 new PortalCacheIndexer<Long, UserRoleKey, Boolean>(
373 new UserRoleKeyIndexEncoder(), _userRolePortalCache);
374
375 private static Log _log = LogFactoryUtil.getLog(PermissionCacheUtil.class);
376
377 private static ThreadLocal<LRUMap> _localCache;
378 private static boolean _localCacheAvailable;
379
380 private static class BagKey implements Serializable {
381
382 @Override
383 public boolean equals(Object obj) {
384 BagKey bagKey = (BagKey)obj;
385
386 if ((bagKey._userId == _userId) && (bagKey._groupId == _groupId)) {
387 return true;
388 }
389
390 return false;
391 }
392
393 @Override
394 public int hashCode() {
395 int hashCode = HashUtil.hash(0, _userId);
396
397 return HashUtil.hash(hashCode, _groupId);
398 }
399
400 private BagKey(long userId, long groupId) {
401 _userId = userId;
402 _groupId = groupId;
403 }
404
405 private static final long serialVersionUID = 1L;
406
407 private final long _groupId;
408 private final long _userId;
409
410 }
411
412 private static class BagKeyIndexEncoder
413 implements IndexEncoder<Long, BagKey> {
414
415 @Override
416 public Long encode(BagKey bagKey) {
417 return bagKey._userId;
418 }
419
420 }
421
422 private static class PermissionKey implements Serializable {
423
424 @Override
425 public boolean equals(Object obj) {
426 PermissionKey permissionKey = (PermissionKey)obj;
427
428 if ((permissionKey._userId == _userId) &&
429 (permissionKey._signedIn == _signedIn) &&
430 (permissionKey._groupId == _groupId) &&
431 Validator.equals(permissionKey._name, _name) &&
432 Validator.equals(permissionKey._primKey, _primKey) &&
433 Validator.equals(permissionKey._actionId, _actionId)) {
434
435 return true;
436 }
437
438 return false;
439 }
440
441 @Override
442 public int hashCode() {
443 int hashCode = HashUtil.hash(0, _userId);
444
445 hashCode = HashUtil.hash(hashCode, _signedIn);
446 hashCode = HashUtil.hash(hashCode, _groupId);
447 hashCode = HashUtil.hash(hashCode, _name);
448 hashCode = HashUtil.hash(hashCode, _primKey);
449 hashCode = HashUtil.hash(hashCode, _actionId);
450
451 return hashCode;
452 }
453
454 private PermissionKey(
455 long userId, boolean signedIn, long groupId, String name,
456 String primKey, String actionId) {
457
458 _userId = userId;
459 _signedIn = signedIn;
460 _groupId = groupId;
461 _name = name;
462 _primKey = primKey;
463 _actionId = actionId;
464 }
465
466 private static final long serialVersionUID = 1L;
467
468 private final String _actionId;
469 private final long _groupId;
470 private final String _name;
471 private final String _primKey;
472 private final boolean _signedIn;
473 private final long _userId;
474
475 }
476
477 private static class PermissionKeyGroupIdIndexEncoder
478 implements IndexEncoder<Long, PermissionKey> {
479
480 @Override
481 public Long encode(PermissionKey permissionKey) {
482 return permissionKey._groupId;
483 }
484
485 }
486
487 private static class PermissionKeyNamePrimKeyIndexEncoder
488 implements IndexEncoder<String, PermissionKey> {
489
490 public static String encode(String name, String primKey) {
491 return name.concat(StringPool.UNDERLINE).concat(primKey);
492 }
493
494 @Override
495 public String encode(PermissionKey permissionKey) {
496 return encode(permissionKey._name, permissionKey._primKey);
497 }
498
499 }
500
501 private static class ResourceBlockIdsBagKey implements Serializable {
502
503 @Override
504 public boolean equals(Object obj) {
505 ResourceBlockIdsBagKey resourceBlockIdsKey =
506 (ResourceBlockIdsBagKey)obj;
507
508 if ((resourceBlockIdsKey._companyId == _companyId) &&
509 (resourceBlockIdsKey._groupId == _groupId) &&
510 (resourceBlockIdsKey._userId == _userId) &&
511 Validator.equals(resourceBlockIdsKey._name, _name)) {
512
513 return true;
514 }
515
516 return false;
517 }
518
519 @Override
520 public int hashCode() {
521 int hashCode = HashUtil.hash(0, _companyId);
522
523 hashCode = HashUtil.hash(hashCode, _groupId);
524 hashCode = HashUtil.hash(hashCode, _userId);
525 hashCode = HashUtil.hash(hashCode, _name);
526
527 return hashCode;
528 }
529
530 private ResourceBlockIdsBagKey(
531 long companyId, long groupId, long userId, String name) {
532
533 _companyId = companyId;
534 _groupId = groupId;
535 _userId = userId;
536 _name = name;
537 }
538
539 private static final long serialVersionUID = 1L;
540
541 private final long _companyId;
542 private final long _groupId;
543 private final String _name;
544 private final long _userId;
545
546 }
547
548 private static class ResourceBlockIdsBagKeyIndexEncoder
549 implements IndexEncoder<String, ResourceBlockIdsBagKey> {
550
551 public static String encode(long companyId, long groupId, String name) {
552 StringBundler sb = new StringBundler(5);
553
554 sb.append(companyId);
555 sb.append(StringPool.UNDERLINE);
556 sb.append(groupId);
557 sb.append(StringPool.UNDERLINE);
558 sb.append(name);
559
560 return sb.toString();
561 }
562
563 @Override
564 public String encode(ResourceBlockIdsBagKey resourceBlockIdsBagKey) {
565 return encode(
566 resourceBlockIdsBagKey._companyId,
567 resourceBlockIdsBagKey._groupId, resourceBlockIdsBagKey._name);
568 }
569
570 }
571
572 private static class UserRoleKey implements Serializable {
573
574 @Override
575 public boolean equals(Object obj) {
576 UserRoleKey userRoleKey = (UserRoleKey)obj;
577
578 if ((userRoleKey._userId == _userId) &&
579 (userRoleKey._roleId == _roleId)) {
580
581 return true;
582 }
583
584 return false;
585 }
586
587 @Override
588 public int hashCode() {
589 int hashCode = HashUtil.hash(0, _userId);
590
591 return HashUtil.hash(hashCode, _roleId);
592 }
593
594 private UserRoleKey(long userId, long roleId) {
595 _userId = userId;
596 _roleId = roleId;
597 }
598
599 private static final long serialVersionUID = 1L;
600
601 private final long _roleId;
602 private final long _userId;
603
604 }
605
606 private static class UserRoleKeyIndexEncoder
607 implements IndexEncoder<Long, UserRoleKey> {
608
609 @Override
610 public Long encode(UserRoleKey userRoleKey) {
611 return userRoleKey._userId;
612 }
613
614 }
615
616 static {
617 if (PropsValues.PERMISSIONS_THREAD_LOCAL_CACHE_MAX_SIZE > 0) {
618 _localCache = new AutoResetThreadLocal<LRUMap>(
619 PermissionCacheUtil.class + "._localCache",
620 new LRUMap(
621 PropsValues.PERMISSIONS_THREAD_LOCAL_CACHE_MAX_SIZE));
622 _localCacheAvailable = true;
623 }
624 }
625
626 }