001/* 002 * Copyright 2017 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.plugins.core.impl.right; 017 018import java.util.Collections; 019import java.util.HashMap; 020import java.util.List; 021import java.util.Map; 022import java.util.Set; 023 024import org.apache.avalon.framework.activity.Initializable; 025import org.apache.avalon.framework.component.Component; 026import org.apache.avalon.framework.service.ServiceException; 027import org.apache.avalon.framework.service.ServiceManager; 028import org.apache.avalon.framework.service.Serviceable; 029import org.apache.commons.collections.CollectionUtils; 030 031import org.ametys.core.cache.AbstractCacheManager; 032import org.ametys.core.cache.Cache; 033import org.ametys.core.group.GroupIdentity; 034import org.ametys.core.right.AccessController; 035import org.ametys.core.right.ProfileAssignmentStorageExtensionPoint; 036import org.ametys.core.right.RightManager; 037import org.ametys.core.right.RightProfilesDAO; 038import org.ametys.core.user.UserIdentity; 039import org.ametys.plugins.core.impl.cache.AbstractCacheKey; 040import org.ametys.runtime.i18n.I18nizableTextParameter; 041import org.ametys.runtime.i18n.I18nizableText; 042import org.ametys.runtime.plugin.component.AbstractLogEnabled; 043 044/** 045 * This class delegates all it can to the profile assignment storage extension point 046 */ 047public abstract class AbstractProfileStorageBasedAccessController extends AbstractLogEnabled implements AccessController, Component, Serviceable, Initializable 048{ 049 /** 050 * The knd of cache to get/set 051 */ 052 protected enum CacheKind 053 { 054 /** for anonymous user */ 055 ANONYMOUS, 056 /** for any connected user */ 057 ANY_CONNECTED_USER, 058 /** for users */ 059 USERS, 060 /** for user */ 061 USER, 062 /** for groups */ 063 GROUPS 064 } 065 066 /** The instance of ObjectUserIdentity for anonymous */ 067 protected static final UserIdentity __ANONYMOUS_USER_IDENTITY = null; 068 /** The instance of ObjectUserIdentity for any connected user */ 069 protected static final UserIdentity __ANY_CONTECTED_USER_IDENTITY = new UserIdentity(null, null); 070 071 /** The extension point for the profile assignment storages */ 072 protected ProfileAssignmentStorageExtensionPoint _profileAssignmentStorageEP; 073 /** The right profile DAO */ 074 protected RightProfilesDAO _rightProfileDAO; 075 /** Cache Manager */ 076 protected AbstractCacheManager _cacheManager; 077 078 private final String _cache1 = RightManager.ROLE + "$" + this.getClass().getName() + "$Cache-1"; 079 080 private final String _cache2 = RightManager.ROLE + "$" + this.getClass().getName() + "$Cache-2"; 081 082 083 @Override 084 public void service(ServiceManager manager) throws ServiceException 085 { 086 _rightProfileDAO = (RightProfilesDAO) manager.lookup(RightProfilesDAO.ROLE); 087 _profileAssignmentStorageEP = (ProfileAssignmentStorageExtensionPoint) manager.lookup(ProfileAssignmentStorageExtensionPoint.ROLE); 088 _cacheManager = (AbstractCacheManager) manager.lookup(AbstractCacheManager.ROLE); 089 } 090 091 public void initialize() throws Exception 092 { 093 if (!_cacheManager.hasCache(_cache1)) 094 { 095 _cacheManager.createRequestCache(_cache1, 096 _buildI18n("PLUGINS_CORE_RIGHT_CACHE_1_LABEL"), 097 _buildI18n("PLUGINS_CORE_RIGHT_CACHE_1_DESCRIPTION"), 098 true); 099 } 100 101 if (!_cacheManager.hasCache(_cache2)) 102 { 103 _cacheManager.createRequestCache(_cache2, 104 _buildI18n("PLUGINS_CORE_RIGHT_CACHE_2_LABEL"), 105 _buildI18n("PLUGINS_CORE_RIGHT_CACHE_2_DESCRIPTION"), 106 true); 107 } 108 109 } 110 111 private I18nizableText _buildI18n(String i18Key) 112 { 113 String catalogue = "plugin.core"; 114 I18nizableText className = new I18nizableText(this.getClass().getSimpleName()); 115 Map<String, I18nizableTextParameter> params = Map.of("id", className); 116 return new I18nizableText(catalogue, i18Key, params); 117 } 118 119 public Map<String, AccessResult> getPermissionByRight(UserIdentity user, Set<GroupIdentity> userGroups, Object object) 120 { 121 Map<String, AccessResult> rights = new HashMap<>(); 122 123 Map<String, AccessResult> permissionsByProfile = _profileAssignmentStorageEP.getPermissionsByProfile(user, userGroups, _convertContext(object)); 124 125 // Convert profile <-> accessresult to right <-> accessresult 126 for (String profileId : permissionsByProfile.keySet()) 127 { 128 List<String> rights2 = _rightProfileDAO.getRights(profileId); 129 for (String rightId : rights2) 130 { 131 rights.put(rightId, AccessResult.merge(permissionsByProfile.get(profileId), rights.get(rightId))); 132 } 133 } 134 135 return rights; 136 } 137 138 public AccessResult getPermission(UserIdentity user, Set<GroupIdentity> userGroups, String rightId, Object object) 139 { 140 Set<String> profilesIds = _rightProfileDAO.getProfilesWithRight(rightId); 141 if (profilesIds == null || profilesIds.isEmpty()) 142 { 143 // No need for cache... 144 return AccessResult.UNKNOWN; 145 } 146 else 147 { 148 Object convertedObject = _convertContext(object); 149 return _getPermission(user, userGroups, profilesIds, object, convertedObject); 150 } 151 } 152 public AccessResult getReadAccessPermission(UserIdentity user, Set<GroupIdentity> userGroups, Object object) 153 { 154 Set<String> profilesIds = Collections.singleton(RightManager.READER_PROFILE_ID); 155 // Some converted context may change so cache must be done with the convertedObject 156 Object convertedObject = _convertContext(object); 157 return _getPermission(user, userGroups, profilesIds, object, convertedObject); 158 } 159 /** 160 * Works for getPermission or getReadAccessPermission 161 * @param user The use 162 * @param userGroups The groups 163 * @param profilesIds The profiles 164 * @param object The original context 165 * @param convertedObject The converted context 166 * @return the computed result 167 */ 168 protected AccessResult _getPermission(UserIdentity user, Set<GroupIdentity> userGroups, Set<String> profilesIds, Object object, Object convertedObject) 169 { 170 @SuppressWarnings("unchecked") 171 Map<UserIdentity, AccessResult> cacheResult = (Map<UserIdentity, AccessResult>) _hasRightResultInSecondCache(convertedObject, profilesIds, CacheKind.USER); 172 if (cacheResult != null && cacheResult.containsKey(user)) 173 { 174 return cacheResult.get(user); 175 } 176 177 Map<String, AccessResult> permissions = _profileAssignmentStorageEP.getPermissions(user, userGroups, profilesIds, convertedObject); 178 AccessResult result = AccessResult.merge(permissions.values()); 179 cacheResult = cacheResult == null ? new HashMap<>() : cacheResult; 180 cacheResult.put(user, result); 181 _putInSecondCache(profilesIds, convertedObject, cacheResult, CacheKind.USER); 182 return result; 183 } 184 185 public AccessResult getPermissionForAnonymous(String rightId, Object object) 186 { 187 Set<String> profilesIds = _rightProfileDAO.getProfilesWithRight(rightId); 188 if (profilesIds == null || profilesIds.isEmpty()) 189 { 190 // No need for cache... 191 return AccessResult.UNKNOWN; 192 } 193 else 194 { 195 // Some converted context may change so cache must be done with the convertedObject 196 Object convertedObject = _convertContext(object); 197 return _getPermissionForAnonymous(profilesIds, object, convertedObject); 198 } 199 } 200 public AccessResult getReadAccessPermissionForAnonymous(Object object) 201 { 202 Set<String> profilesIds = Collections.singleton(RightManager.READER_PROFILE_ID); 203 // Some converted context may change so cache must be done with the convertedObject 204 Object convertedObject = _convertContext(object); 205 return _getPermissionForAnonymous(profilesIds, object, convertedObject); 206 } 207 /** 208 * Works for getPermissionForAnonymous and getReadAccessPermissionForAnonymous 209 * @param profilesIds The profiles ids 210 * @param object The context 211 * @param convertedObject The converted context 212 * @return The access result 213 */ 214 protected AccessResult _getPermissionForAnonymous(Set<String> profilesIds, Object object, Object convertedObject) 215 { 216 // Try to retrieve in second cache 217 AccessResult cacheResult = (AccessResult) _hasRightResultInSecondCache(convertedObject, profilesIds, CacheKind.ANONYMOUS); 218 if (cacheResult != null) 219 { 220 return cacheResult; 221 } 222 223 AccessResult result = _profileAssignmentStorageEP.getPermissionForAnonymous(profilesIds, convertedObject); 224 _putInSecondCache(profilesIds, convertedObject, result, CacheKind.ANONYMOUS); 225 return result; 226 } 227 228 public AccessResult getPermissionForAnyConnectedUser(String rightId, Object object) 229 { 230 Set<String> profilesIds = _rightProfileDAO.getProfilesWithRight(rightId); 231 if (profilesIds == null || profilesIds.isEmpty()) 232 { 233 // No need for cache... 234 return AccessResult.UNKNOWN; 235 } 236 else 237 { 238 // Some converted context may change so cache must be done with the convertedObject 239 Object convertedObject = _convertContext(object); 240 return _getPermissionForAnyConnectedUser(profilesIds, object, convertedObject); 241 } 242 } 243 public AccessResult getReadAccessPermissionForAnyConnectedUser(Object object) 244 { 245 Set<String> profilesIds = Collections.singleton(RightManager.READER_PROFILE_ID); 246 // Some converted context may change so cache must be done with the convertedObject 247 Object convertedObject = _convertContext(object); 248 return _getPermissionForAnyConnectedUser(profilesIds, object, convertedObject); 249 } 250 /** 251 * Works for getPermissionForAnyConnectedUser and getReadAccessPermissionForAnyConnectedUser 252 * @param profilesIds The profiles ids 253 * @param object The context 254 * @param convertedObject The converted context 255 * @return the access result 256 */ 257 protected AccessResult _getPermissionForAnyConnectedUser(Set<String> profilesIds, Object object, Object convertedObject) 258 { 259 // Try to retrieve in second cache 260 AccessResult cacheResult = (AccessResult) _hasRightResultInSecondCache(convertedObject, profilesIds, CacheKind.ANY_CONNECTED_USER); 261 if (cacheResult != null) 262 { 263 return cacheResult; 264 } 265 266 AccessResult result = _profileAssignmentStorageEP.getPermissionForAnyConnectedUser(profilesIds, convertedObject); 267 _putInSecondCache(profilesIds, convertedObject, result, CacheKind.ANY_CONNECTED_USER); 268 return result; 269 } 270 271 public Map<UserIdentity, AccessResult> getPermissionByUser(String rightId, Object object) 272 { 273 Set<String> profilesIds = _rightProfileDAO.getProfilesWithRight(rightId); 274 if (profilesIds == null || profilesIds.isEmpty()) 275 { 276 // No need for cache... 277 return Collections.EMPTY_MAP; 278 } 279 else 280 { 281 // Some converted context may change so cache must be done with the convertedObject 282 Object convertedObject = _convertContext(object); 283 return _getPermissionByUser(profilesIds, object, convertedObject); 284 } 285 } 286 public Map<UserIdentity, AccessResult> getReadAccessPermissionByUser(Object object) 287 { 288 Set<String> profilesIds = Collections.singleton(RightManager.READER_PROFILE_ID); 289 // Some converted context may change so cache must be done with the convertedObject 290 Object convertedObject = _convertContext(object); 291 return _getPermissionByUser(profilesIds, object, convertedObject); 292 } 293 /** 294 * Works for getPermissionByUser and getReadAccessPermissionByUser 295 * @param profilesIds The profiles ids 296 * @param object The context 297 * @param convertedObject The converted context 298 * @return The users and their access results 299 */ 300 protected Map<UserIdentity, AccessResult> _getPermissionByUser(Set<String> profilesIds, Object object, Object convertedObject) 301 { 302 // Try to retrieve in second cache 303 @SuppressWarnings("unchecked") 304 Map<UserIdentity, AccessResult> cacheResult = (Map<UserIdentity, AccessResult>) _hasRightResultInSecondCache(convertedObject, profilesIds, CacheKind.USERS); 305 if (cacheResult != null) 306 { 307 return cacheResult; 308 } 309 310 Map<UserIdentity, AccessResult> result = _profileAssignmentStorageEP.getPermissionsByUser(profilesIds, convertedObject); 311 _putInSecondCache(profilesIds, convertedObject, result, CacheKind.USERS); 312 return result; 313 } 314 315 public Map<GroupIdentity, AccessResult> getPermissionByGroup(String rightId, Object object) 316 { 317 Set<String> profilesIds = _rightProfileDAO.getProfilesWithRight(rightId); 318 if (profilesIds == null || profilesIds.isEmpty()) 319 { 320 // No need for cache... 321 return Collections.EMPTY_MAP; 322 } 323 else 324 { 325 // Some converted context may change so cache must be done with the convertedObject 326 Object convertedObject = _convertContext(object); 327 return _getPermissionByGroup(profilesIds, object, convertedObject); 328 } 329 } 330 public Map<GroupIdentity, AccessResult> getReadAccessPermissionByGroup(Object object) 331 { 332 Set<String> profilesIds = Collections.singleton(RightManager.READER_PROFILE_ID); 333 // Some converted context may change so cache must be done with the convertedObject 334 Object convertedObject = _convertContext(object); 335 return _getPermissionByGroup(profilesIds, object, convertedObject); 336 } 337 /** 338 * Works for getPermissionByGroup and getReadAccessPermissionByGroup 339 * @param profilesIds The profiles ids 340 * @param object The context 341 * @param convertedObject The converted context 342 * @return The users and their access results 343 */ 344 protected Map<GroupIdentity, AccessResult> _getPermissionByGroup(Set<String> profilesIds, Object object, Object convertedObject) 345 { 346 // Try to retrieve in second cache 347 @SuppressWarnings("unchecked") 348 Map<GroupIdentity, AccessResult> cacheResult = (Map<GroupIdentity, AccessResult>) _hasRightResultInSecondCache(convertedObject, profilesIds, CacheKind.GROUPS); 349 if (cacheResult != null) 350 { 351 return cacheResult; 352 } 353 354 Map<GroupIdentity, AccessResult> result = _profileAssignmentStorageEP.getPermissionsByGroup(profilesIds, convertedObject); 355 _putInSecondCache(profilesIds, convertedObject, result, CacheKind.GROUPS); 356 return result; 357 } 358 359 /** 360 * For methods getXXXXPermissionYYY allow to have a modification of the context before transfering it to the profile assignment storage extension point 361 * The default implemenation keep the context as it is 362 * @param initialContext The right context that is supported 363 * @return the context modified 364 */ 365 protected Object _convertContext(Object initialContext) 366 { 367 return initialContext; 368 } 369 370 public boolean hasAnonymousAnyReadAccessPermissionOnWorkspace(Set<Object> workspacesContexts) 371 { 372 Set<String> profilesIds = Collections.singleton(RightManager.READER_PROFILE_ID); 373 return _hasAnonymousAnyPermissionOnWorkspace(workspacesContexts, profilesIds); 374 } 375 public boolean hasAnonymousAnyPermissionOnWorkspace(Set<Object> workspacesContexts, String rightId) 376 { 377 Set<String> profilesIds = _rightProfileDAO.getProfilesWithRight(rightId); 378 return _hasAnonymousAnyPermissionOnWorkspace(workspacesContexts, profilesIds); 379 } 380 private boolean _hasAnonymousAnyPermissionOnWorkspace(Set<Object> workspacesContexts, Set<String> profilesIds) 381 { 382 // Try to retrieve in first cache (the one which manages non-null contexts) 383 Boolean cacheResult = _hasRightResultInFirstCache(__ANONYMOUS_USER_IDENTITY, profilesIds, workspacesContexts); 384 if (cacheResult != null) 385 { 386 return cacheResult; 387 } 388 389 // Otherwise continue 390 Set<? extends Object> rootContexts = _convertWorkspaceToRootRightContexts(workspacesContexts); 391 392 Set<String> determinedProfiles = profilesIds; 393 boolean rightResult = false; 394 395 if (CollectionUtils.isNotEmpty(rootContexts)) 396 { 397 Set<String> hasAnonymousAnyPermission = _profileAssignmentStorageEP.hasAnonymousAnyPermission(rootContexts, profilesIds); 398 if (!hasAnonymousAnyPermission.isEmpty()) 399 { 400 rightResult = true; 401 determinedProfiles = hasAnonymousAnyPermission; 402 } 403 } 404 405 _putInFirstCache(__ANONYMOUS_USER_IDENTITY, determinedProfiles, workspacesContexts, rightResult); 406 return rightResult; 407 } 408 409 public boolean hasAnyConnectedUserAnyReadAccessPermissionOnWorkspace(Set<Object> workspacesContexts) 410 { 411 Set<String> profilesIds = Collections.singleton(RightManager.READER_PROFILE_ID); 412 return _hasAnyConnectedUserAnyPermissionOnWorkspace(workspacesContexts, profilesIds); 413 } 414 public boolean hasAnyConnectedUserAnyPermissionOnWorkspace(Set<Object> workspacesContexts, String rightId) 415 { 416 Set<String> profilesIds = _rightProfileDAO.getProfilesWithRight(rightId); 417 return _hasAnyConnectedUserAnyPermissionOnWorkspace(workspacesContexts, profilesIds); 418 } 419 private boolean _hasAnyConnectedUserAnyPermissionOnWorkspace(Set<Object> workspacesContexts, Set<String> profilesIds) 420 { 421 // Try to retrieve in first cache (the one which manages non-null contexts) 422 Boolean cacheResult = _hasRightResultInFirstCache(__ANY_CONTECTED_USER_IDENTITY, profilesIds, workspacesContexts); 423 if (cacheResult != null) 424 { 425 return cacheResult; 426 } 427 428 // Otherwise continue 429 Set<? extends Object> rootContexts = _convertWorkspaceToRootRightContexts(workspacesContexts); 430 431 Set<String> determinedProfiles = profilesIds; 432 boolean rightResult = false; 433 434 if (CollectionUtils.isNotEmpty(rootContexts)) 435 { 436 Set<String> hasAnyConnectedUserAnyPermission = _profileAssignmentStorageEP.hasAnyConnectedUserAnyPermission(rootContexts, profilesIds); 437 if (!hasAnyConnectedUserAnyPermission.isEmpty()) 438 { 439 rightResult = true; 440 determinedProfiles = hasAnyConnectedUserAnyPermission; 441 } 442 } 443 444 _putInFirstCache(__ANY_CONTECTED_USER_IDENTITY, determinedProfiles, workspacesContexts, rightResult); 445 return rightResult; 446 } 447 448 public boolean hasUserAnyReadAccessPermissionOnWorkspace(Set<Object> workspacesContexts, UserIdentity user, Set<GroupIdentity> userGroups) 449 { 450 Set<String> profilesIds = Collections.singleton(RightManager.READER_PROFILE_ID); 451 return _hasUserAnyPermissionOnWorkspace(workspacesContexts, user, userGroups, profilesIds); 452 } 453 public boolean hasUserAnyPermissionOnWorkspace(Set<Object> workspacesContexts, UserIdentity user, Set<GroupIdentity> userGroups, String rightId) 454 { 455 Set<String> profilesIds = _rightProfileDAO.getProfilesWithRight(rightId); 456 return _hasUserAnyPermissionOnWorkspace(workspacesContexts, user, userGroups, profilesIds); 457 } 458 private boolean _hasUserAnyPermissionOnWorkspace(Set<Object> workspacesContexts, UserIdentity user, Set<GroupIdentity> userGroups, Set<String> profilesIds) 459 { 460 // Try to retrieve in first cache (the one which manages non-null contexts) 461 Boolean cacheResult = _hasRightResultInFirstCache(user, profilesIds, workspacesContexts); 462 if (cacheResult != null) 463 { 464 return cacheResult; 465 } 466 467 // Otherwise continue 468 Set<? extends Object> rootContexts = _convertWorkspaceToRootRightContexts(workspacesContexts); 469 470 Set<String> determinedProfiles = profilesIds; 471 boolean rightResult = false; 472 473 if (CollectionUtils.isNotEmpty(rootContexts)) 474 { 475 Set<String> hasUserAnyPermission = _profileAssignmentStorageEP.hasUserAnyPermission(rootContexts, user, userGroups, profilesIds); 476 if (!hasUserAnyPermission.isEmpty()) 477 { 478 rightResult = true; 479 determinedProfiles = hasUserAnyPermission; 480 } 481 } 482 483 _putInFirstCache(user, determinedProfiles, workspacesContexts, rightResult); 484 return rightResult; 485 } 486 487 /** 488 * Get the current workspaces contexts and turn it into root contexts in order to allow methods hasXXXAnyPermissionOnWorkspace to work 489 * @param workspacesContexts The workspace contexts. Such as '/${WorkspaceName}', '/admin' 490 * @return A null or empty set if the current AccessController does not apply to any workspace context, or the root object where ProfileAssignmentStorageExtension should start looking at to find any permission 491 */ 492 protected abstract Set<? extends Object> _convertWorkspaceToRootRightContexts(Set<Object> workspacesContexts); 493 494 495 496 497 498 499 /** 500 * Seek in cache 501 * @param userIdentity The user identity or AbstractProfileStorageBasedAccessController.__ANONYMOUS_USER_IDENTITY or AbstractProfileStorageBasedAccessController.__ANY_CONTECTED_USER_IDENTITY 502 * @param profilesIds The profiles identifiers 503 * @param object The context 504 * @return true or false if in cache. null otherwise 505 */ 506 protected Boolean _hasRightResultInFirstCache(UserIdentity userIdentity, Set<String> profilesIds, Object object) 507 { 508 // On the contrary of the other cache, this one is split between profiles, as we check for the first true result (no negativity) 509 510 if (profilesIds == null || profilesIds.isEmpty()) 511 { 512 // No need for cache... 513 return false; 514 } 515 516 Cache<Cache1Key, Boolean> mapCache = _cacheManager.get(_cache1); 517 if (mapCache != null) 518 { 519 int negativeProfiles = 0; 520 521 for (String profileId: profilesIds) 522 { 523 Cache1Key key = Cache1Key.of(userIdentity, profileId, object); 524 if (mapCache.hasKey(key)) 525 { 526 if (mapCache.get(key)) 527 { 528 getLogger().debug("Find entry in cache for [{}, {}, {}] => true", userIdentity, profilesIds, object); 529 return true; 530 } 531 else 532 { 533 negativeProfiles++; 534 } 535 } 536 } 537 538 if (negativeProfiles == profilesIds.size()) 539 { 540 // All required profiles were negative in cache 541 return false; 542 } 543 } 544 getLogger().debug("Did not find entry in cache for [{}, {}, {}]", userIdentity, profilesIds, object); 545 return null; 546 } 547 548 /** 549 * Add to cache 550 * @param userIdentity The user identity or AbstractProfileStorageBasedAccessController.__ANONYMOUS_USER_IDENTITY or AbstractProfileStorageBasedAccessController.__ANY_CONTECTED_USER_IDENTITY 551 * @param profilesIds The profiles identifiers 552 * @param object The context 553 * @param rightResult The cache value. true if hasXXX or false otherwise. 554 */ 555 protected void _putInFirstCache(UserIdentity userIdentity, Set<String> profilesIds, Object object, boolean rightResult) 556 { 557 // On the contrary of the other cache, this one is split between profiles, as we check for the first true result (no negativity) 558 559 Cache<Cache1Key, Boolean> mapCache = _cacheManager.get(_cache1); 560 if (mapCache != null) 561 { 562 for (String profileId: profilesIds) 563 { 564 mapCache.put(Cache1Key.of(userIdentity, profileId, object), rightResult); 565 } 566 } 567 } 568 569 /** 570 * Seek in cache 571 * @param object The context 572 * @param profilesIds The set of profile ids to consider 573 * @return The cached result per group. null otherwise 574 * @param key The kind of cache to use 575 */ 576 protected Object _hasRightResultInSecondCache(Object object, Set<String> profilesIds, CacheKind key) 577 { 578 Cache<Cache2Key, Object> mapCache = _cacheManager.get(_cache2); 579 580 Object cacheResult = mapCache.get(Cache2Key.of(profilesIds, object, key)); 581 if (cacheResult != null) 582 { 583 getLogger().debug("Find entry in cache for [{}, {}, {}] => {}", profilesIds, object, key, cacheResult); 584 return cacheResult; 585 } 586 587 getLogger().debug("Did not find entry in cache for [{}, {}, {}]", profilesIds, object, key); 588 return null; 589 } 590 591 /** 592 * Add to cache 593 * @param profilesIds The profiles ids to consider 594 * @param object The context 595 * @param result The result 596 * @param key The kind of cache to use 597 */ 598 protected void _putInSecondCache(Set<String> profilesIds, Object object, Object result, CacheKind key) 599 { 600 Cache<Cache2Key, Object> mapCache = _cacheManager.get(_cache2); 601 602 if (mapCache != null) 603 { 604 mapCache.put(Cache2Key.of(profilesIds, object, key), result); 605 } 606 607 } 608 609 static class Cache1Key extends AbstractCacheKey 610 { 611 Cache1Key(UserIdentity userIdentity, String profileId, Object object) 612 { 613 super(userIdentity, profileId, object); 614 } 615 616 static Cache1Key of(UserIdentity userIdentity, String profileId, Object object) 617 { 618 return new Cache1Key(userIdentity, profileId, object); 619 } 620 621 } 622 static class Cache2Key extends AbstractCacheKey 623 { 624 Cache2Key(Set<String> profileIds, Object object, CacheKind cacheKind) 625 { 626 super(profileIds, object, cacheKind); 627 } 628 629 static Cache2Key of(Set<String> profileIds, Object object, CacheKind cacheKind) 630 { 631 return new Cache2Key(profileIds, object, cacheKind); 632 } 633 634 } 635 636}