@Test public void loadWithConflictingInsertionException() throws Exception { DocumentReference userReference = new DocumentReference("wiki", "Users", "mflorea"); UserSecurityReference user = securityReferenceFactory.newUserReference(userReference); DocumentReference documentReference = new DocumentReference("wiki", "Space", "Document"); SecurityReference entity = securityReferenceFactory.newEntityReference(documentReference); SecurityRuleEntry documentEntry = mock(SecurityRuleEntry.class, "document"); when(documentEntry.getReference()).thenReturn(entity); when(documentEntry.isEmpty()).thenReturn(true); SecurityRuleEntry spaceEntry = mock(SecurityRuleEntry.class, "space"); when(spaceEntry.getReference()).thenReturn(entity.getParentSecurityReference()); when(spaceEntry.isEmpty()).thenReturn(true); SecurityRuleEntry wikiEntry = mock(SecurityRuleEntry.class, "wiki"); when(wikiEntry.getReference()).thenReturn(entity.getParentSecurityReference().getParentSecurityReference()); when(wikiEntry.isEmpty()).thenReturn(true); SecurityCache securityCache = mocker.getInstance(org.xwiki.security.authorization.cache.SecurityCache.class); when(securityCache.get(entity)).thenReturn(documentEntry); when(securityCache.get(entity.getParentSecurityReference())).thenReturn(spaceEntry); when(securityCache.get(entity.getParentSecurityReference().getParentSecurityReference())).thenReturn(wikiEntry); when(securityCache.getGroupsFor(user, null)).thenReturn(null); UserBridge userBridge = mocker.getInstance(UserBridge.class); DocumentReference groupReference = new DocumentReference("wiki", "Groups", "AllGroup"); Set<GroupSecurityReference> groups = Collections.singleton(securityReferenceFactory.newGroupReference(groupReference)); when(userBridge.getAllGroupsFor(user, userReference.getWikiReference())).thenReturn(groups); SecurityAccessEntry securityAccessEntry = mock(SecurityAccessEntry.class); AuthorizationSettler authorizationSettler = mocker.getInstance(AuthorizationSettler.class); Deque<SecurityRuleEntry> securityRuleEntries = new LinkedList<SecurityRuleEntry>(Arrays.asList(documentEntry, spaceEntry, wikiEntry)); when(authorizationSettler.settle(user, groups, securityRuleEntries)).thenReturn(securityAccessEntry); doThrow(ConflictingInsertionException.class).when(securityCache).add(securityAccessEntry); doThrow(ConflictingInsertionException.class).when(securityCache).add(securityAccessEntry, null); try { securityCacheLoader.load(user, entity); fail(); } catch (AuthorizationException e) { assertEquals("Failed to load the cache in 5 attempts. Giving up. when checking " + "access to [wiki:Space.Document] for user [wiki:Users.mflorea]", e.getMessage()); assertTrue(ExceptionUtils.getRootCauseMessage(e).contains("ConflictingInsertionException")); } assertEquals(1, this.logRule.size()); assertEquals( "Failed to load the cache in 5 attempts. Giving up. For user [Document wiki:Users.mflorea] and entity [Document wiki:Space.Document].", this.logRule.getMessage(0)); }
@Override public SecurityAccessEntry load(UserSecurityReference user, SecurityReference entity) throws AuthorizationException { int retries = 0; Exception lastException; while (true) { rulesInvalidator.suspend(); try { retries++; return loadRequiredEntries(user, entity); } catch (ParentEntryEvictedException e) { lastException = e; if (retries < MAX_RETRIES) { this.logger.debug("The parent entry was evicted. Have tried {} times. Trying again...", retries); continue; } } catch (ConflictingInsertionException e) { lastException = e; if (retries < MAX_RETRIES) { this.logger.debug("There were conflicting insertions. Have tried {} times. Retrying...", retries); continue; } } finally { rulesInvalidator.resume(); } String message = String.format("Failed to load the cache in %d attempts. Giving up.", retries); this.logger.error(String.format("%s For user [%s] and entity [%s].", message, user, entity)); throw new AuthorizationException(user.getOriginalDocumentReference(), entity.getOriginalReference(), message, lastException); } }
DefaultSecurityCacheLoader implements SecurityCacheLoader { @Override public SecurityAccessEntry load(UserSecurityReference user, SecurityReference entity) throws AuthorizationException { int retries = 0; Exception lastException; while (true) { rulesInvalidator.suspend(); try { retries++; return loadRequiredEntries(user, entity); } catch (ParentEntryEvictedException e) { lastException = e; if (retries < MAX_RETRIES) { this.logger.debug("The parent entry was evicted. Have tried {} times. Trying again...", retries); continue; } } catch (ConflictingInsertionException e) { lastException = e; if (retries < MAX_RETRIES) { this.logger.debug("There were conflicting insertions. Have tried {} times. Retrying...", retries); continue; } } finally { rulesInvalidator.resume(); } String message = String.format("Failed to load the cache in %d attempts. Giving up.", retries); this.logger.error(String.format("%s For user [%s] and entity [%s].", message, user, entity)); throw new AuthorizationException(user.getOriginalDocumentReference(), entity.getOriginalReference(), message, lastException); } } }
DefaultSecurityCacheLoader implements SecurityCacheLoader { @Override public SecurityAccessEntry load(UserSecurityReference user, SecurityReference entity) throws AuthorizationException { int retries = 0; Exception lastException; while (true) { rulesInvalidator.suspend(); try { retries++; return loadRequiredEntries(user, entity); } catch (ParentEntryEvictedException e) { lastException = e; if (retries < MAX_RETRIES) { this.logger.debug("The parent entry was evicted. Have tried {} times. Trying again...", retries); continue; } } catch (ConflictingInsertionException e) { lastException = e; if (retries < MAX_RETRIES) { this.logger.debug("There were conflicting insertions. Have tried {} times. Retrying...", retries); continue; } } finally { rulesInvalidator.resume(); } String message = String.format("Failed to load the cache in %d attempts. Giving up.", retries); this.logger.error(String.format("%s For user [%s] and entity [%s].", message, user, entity)); throw new AuthorizationException(user.getOriginalDocumentReference(), entity.getOriginalReference(), message, lastException); } }  }
DefaultSecurityCacheLoader implements SecurityCacheLoader { @Override public SecurityAccessEntry load(UserSecurityReference user, SecurityReference entity) throws AuthorizationException { int retries = 0; Exception lastException; while (true) { rulesInvalidator.suspend(); try { retries++; return loadRequiredEntries(user, entity); } catch (ParentEntryEvictedException e) { lastException = e; if (retries < MAX_RETRIES) { this.logger.debug("The parent entry was evicted. Have tried {} times. Trying again...", retries); continue; } } catch (ConflictingInsertionException e) { lastException = e; if (retries < MAX_RETRIES) { this.logger.debug("There were conflicting insertions. Have tried {} times. Retrying...", retries); continue; } } finally { rulesInvalidator.resume(); } String message = String.format("Failed to load the cache in %d attempts. Giving up.", retries); this.logger.error(String.format("%s For user [%s] and entity [%s].", message, user, entity)); throw new AuthorizationException(user.getOriginalDocumentReference(), entity.getOriginalReference(), message, lastException); } }  @Override SecurityAccessEntry load(UserSecurityReference user, SecurityReference entity); }
DefaultSecurityCacheLoader implements SecurityCacheLoader { @Override public SecurityAccessEntry load(UserSecurityReference user, SecurityReference entity) throws AuthorizationException { int retries = 0; Exception lastException; while (true) { rulesInvalidator.suspend(); try { retries++; return loadRequiredEntries(user, entity); } catch (ParentEntryEvictedException e) { lastException = e; if (retries < MAX_RETRIES) { this.logger.debug("The parent entry was evicted. Have tried {} times. Trying again...", retries); continue; } } catch (ConflictingInsertionException e) { lastException = e; if (retries < MAX_RETRIES) { this.logger.debug("There were conflicting insertions. Have tried {} times. Retrying...", retries); continue; } } finally { rulesInvalidator.resume(); } String message = String.format("Failed to load the cache in %d attempts. Giving up.", retries); this.logger.error(String.format("%s For user [%s] and entity [%s].", message, user, entity)); throw new AuthorizationException(user.getOriginalDocumentReference(), entity.getOriginalReference(), message, lastException); } }  @Override SecurityAccessEntry load(UserSecurityReference user, SecurityReference entity);  }