DefaultRightLoader extends AbstractLogEnabled implements RightLoader { @Override public AccessLevel load(DocumentReference user, EntityReference entity) throws RightServiceException { int retries = 0; RETRY: while (true) { rightCacheInvalidator.suspend(); try { retries++; return loadRequiredEntries(user, entity); } catch (ParentEntryEvictedException e) { if (retries < MAX_RETRIES) { getLogger().debug("The parent entry was evicted. Have tried " + retries + " times. Trying again..."); continue RETRY; } } catch (ConflictingInsertionException e) { if (retries < MAX_RETRIES) { getLogger().debug("There were conflicting insertions. Have tried " + retries + " times. Retrying..."); continue RETRY; } } finally { rightCacheInvalidator.resume(); } getLogger().error("Failed to load the cache in " + retries + " attempts. Giving up."); throw new RightServiceException(); } }  @Override AccessLevel load(DocumentReference user, EntityReference entity);  }
@Test public void testRightLoader() { DocumentReference userX = docRefResolver.resolve("wikiY:XWiki.userX"); DocumentReference userY = docRefResolver.resolve("wikiY:XWiki.userY"); DocumentReference userZ = docRefResolver.resolve("xwiki:XWiki.userZ"); DocumentReference admin = docRefResolver.resolve("xwiki:XWiki.Admin"); MockDocument wikiDocument = new MockDocument("xwiki:XWiki.XWikiPreferences", "xwiki:XWiki.Admin"); MockDocument allGroupDocument = MockDocument.newGroupDocument("xwiki:XWiki.XWikiAllGroup", new String[]{"wikiY:XWiki.userX", "wikiY:XWiki.userY" }); wiki.add(new MockDocument(userX, "xwiki:XWiki.Admin") .allowLocal(asList(new Right[]{EDIT }), asList(new String[]{"wikiY:XWiki.userX"}), EMPTY_LIST )) .add(new MockDocument(userY, "xwiki:XWiki.Admin") .allowLocal(asList(new Right[]{EDIT }), asList(new String[]{"wikiY:XWiki.userY"}), EMPTY_LIST )) .add(wikiDocument) .add(allGroupDocument); try { mockery.checking(new Expectations() {{ allowing(mockGroupService) .getAllGroupsNamesForMember("wikiY:XWiki.userX", Integer.MAX_VALUE, 0, xwikiContext); will(returnValue(asList(new String[]{"XWiki.XWikiAllGroup"}))); allowing(mockGroupService) .getAllGroupsNamesForMember("wikiY:XWiki.userY", Integer.MAX_VALUE, 0, xwikiContext); will(returnValue(asList(new String[]{"XWiki.XWikiAllGroup"}))); }}); RightLoader loader = getComponentManager().lookup(RightLoader.class); RightCache cache = getComponentManager().lookup(RightCache.class); RightCacheInvalidator invalidator = getComponentManager().lookup(RightCacheInvalidator.class); AccessLevel edit = AccessLevel.DEFAULT_ACCESS_LEVEL.clone(); edit.allow(EDIT); AccessLevel level = loader.load(userX, userX); System.out.println("Level is " + level + ", expected " + edit); assertTrue(level.equals(edit)); RightCacheEntry entry = cache.get(cache.getRightCacheKey(userX), cache.getRightCacheKey(userX)); assertTrue(entry != null); assertTrue(entry.equals(level)); entry = cache.get(cache.getRightCacheKey(userX)); assertTrue(entry != null); assertTrue(entry.getType() == RightCacheEntry.Type.HAVE_OBJECTS); entry = cache.get(cache.getRightCacheKey(userX.getParent())); assertTrue(entry != null); assertTrue(entry.getType() == RightCacheEntry.Type.HAVE_NO_OBJECTS); entry = cache.get(cache.getRightCacheKey(userX.getParent().getParent())); assertTrue(entry != null); assertTrue(entry.getType() == RightCacheEntry.Type.HAVE_OBJECTS); ((EventListener) invalidator).onEvent(null, wikiDocument, null); entry = cache.get(cache.getRightCacheKey(userX), cache.getRightCacheKey(userX)); assertTrue(entry == null); entry = cache.get(cache.getRightCacheKey(userX)); assertTrue(entry == null); entry = cache.get(cache.getRightCacheKey(userX.getParent())); assertTrue(entry == null); entry = cache.get(cache.getRightCacheKey(userX.getParent().getParent())); assertTrue(entry == null); wikiDocument.denyGlobal(asList(new Right[]{COMMENT }), EMPTY_LIST, asList(new String[]{"wikiY:XWiki.XWikiAllGroup" })); AccessLevel editNoComment = edit.clone(); editNoComment.deny(COMMENT); level = loader.load(userX, userX); assertTrue(level.equals(editNoComment)); mockery.checking(new Expectations() {{ allowing(mockGroupService).getAllMembersNamesForGroup("xwiki:XWiki.GroupX", 100, 0, xwikiContext); will(returnValue(asList(new String[]{"wikiY:XWiki.userX"}))); }}); MockDocument group = MockDocument.newGroupDocument("XWiki.GroupX", new String[] {"wikiY:XWiki.userX" } ); wiki.add(group); ((EventListener) invalidator).onEvent(null, group, null); entry = cache.get(cache.getRightCacheKey(userX)); assertTrue("Invalidating cache after group update", entry == null); entry = cache.get(cache.getRightCacheKey(userX), cache.getRightCacheKey(userX)); assertTrue("Invalidating cache after group update", entry == null); entry = cache.get(cache.getRightCacheKey(userX.getParent())); assertTrue("Invalidating cache after group update", entry != null); entry = cache.get(cache.getRightCacheKey(userX.getParent().getParent())); assertTrue("Invalidating cache after group update", entry != null); } catch (Exception e) { LOG.error("Caught exception.", e); assert false; } }