1. Project Clover database Sat Feb 2 2019 06:45:20 CET
  2. Package org.xwiki.user.internal.group

File DefaultGroupManager.java

 

Coverage histogram

../../../../../img/srcFileCovDistChart9.png
41% of files have more coverage

Code metrics

64
144
11
1
401
285
52
0.36
13.09
11
4.73

Classes

Class Line # Actions
DefaultGroupManager 57 144 0% 52 33
0.8493150584.9%
 

Contributing tests

This file is covered by 10 tests. .

Source view

1    /*
2    * See the NOTICE file distributed with this work for additional
3    * information regarding copyright ownership.
4    *
5    * This is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU Lesser General Public License as
7    * published by the Free Software Foundation; either version 2.1 of
8    * the License, or (at your option) any later version.
9    *
10    * This software is distributed in the hope that it will be useful,
11    * but WITHOUT ANY WARRANTY; without even the implied warranty of
12    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13    * Lesser General Public License for more details.
14    *
15    * You should have received a copy of the GNU Lesser General Public
16    * License along with this software; if not, write to the Free
17    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19    */
20    package org.xwiki.user.internal.group;
21   
22    import java.util.Collection;
23    import java.util.Collections;
24    import java.util.LinkedHashSet;
25    import java.util.Set;
26    import java.util.TreeSet;
27   
28    import javax.inject.Inject;
29    import javax.inject.Provider;
30    import javax.inject.Singleton;
31   
32    import org.xwiki.component.annotation.Component;
33    import org.xwiki.model.internal.reference.EntityReferenceFactory;
34    import org.xwiki.model.reference.DocumentReference;
35    import org.xwiki.model.reference.DocumentReferenceResolver;
36    import org.xwiki.model.reference.EntityReferenceSerializer;
37    import org.xwiki.model.reference.WikiReference;
38    import org.xwiki.user.group.GroupException;
39    import org.xwiki.user.group.GroupManager;
40    import org.xwiki.user.group.WikiTarget;
41    import org.xwiki.user.internal.group.AbstractGroupCache.GroupCacheEntry;
42    import org.xwiki.wiki.descriptor.WikiDescriptorManager;
43    import org.xwiki.wiki.manager.WikiManagerException;
44   
45    import com.xpn.xwiki.XWikiContext;
46    import com.xpn.xwiki.XWikiException;
47    import com.xpn.xwiki.user.api.XWikiGroupService;
48   
49    /**
50    * Fast access to group membership.
51    *
52    * @version $Id: 53b166da432f48c64960ef339e874f37a0b5ce8e $
53    * @since 10.8RC1
54    */
55    @Component
56    @Singleton
 
57    public class DefaultGroupManager implements GroupManager
58    {
59    @Inject
60    private GroupsCache groupsCache;
61   
62    @Inject
63    private MembersCache membersCache;
64   
65    @Inject
66    private WikiDescriptorManager wikis;
67   
68    @Inject
69    private Provider<XWikiContext> xcontextProvider;
70   
71    @Inject
72    private EntityReferenceSerializer<String> serializer;
73   
74    @Inject
75    private DocumentReferenceResolver<String> resolver;
76   
77    @Inject
78    private EntityReferenceFactory referenceFactory;
79   
 
80  468 toggle private Collection<String> getSearchWikis(DocumentReference reference, WikiTarget wikiTarget, boolean resolve)
81    throws GroupException
82    {
83  468 Collection<String> cacheWikis;
84   
85  468 switch ((WikiTarget) wikiTarget) {
86  32 case ENTITY:
87  32 cacheWikis = Collections.singleton(reference.getWikiReference().getName());
88  32 break;
89  8 case ENTITY_AND_CURRENT:
90  8 cacheWikis = new TreeSet<>();
91  8 cacheWikis.add(reference.getWikiReference().getName());
92  8 cacheWikis.add(this.wikis.getCurrentWikiId());
93  8 break;
94   
95  428 default:
96  428 if (resolve) {
97  89 try {
98  89 cacheWikis = this.wikis.getAllIds();
99    } catch (WikiManagerException e) {
100  0 throw new GroupException("Failed to get all wikis", e);
101    }
102    } else {
103  339 cacheWikis = null;
104    }
105  428 break;
106    }
107   
108  468 return cacheWikis;
109    }
110   
 
111  79 toggle private Collection<String> getSearchWikis(DocumentReference reference, Collection<?> wikiTarget, boolean resolve)
112    {
113  79 Collection<String> searchWikis = new TreeSet<>();
114   
115  79 for (Object wiki : wikiTarget) {
116  153 if (wiki instanceof String) {
117  153 searchWikis.add((String) wiki);
118  0 } else if (wiki instanceof WikiReference) {
119  0 searchWikis.add(((WikiReference) wiki).getName());
120  0 } else if (wiki instanceof WikiTarget) {
121  0 searchWikis.addAll(getSearchWikis(reference, wikiTarget, resolve));
122    }
123    }
124   
125  79 return searchWikis;
126    }
127   
 
128  583 toggle private Collection<String> getSearchWikis(DocumentReference reference, Object wikiTarget, boolean resolve)
129    throws GroupException
130    {
131  583 Collection<String> cacheWikis;
132   
133  583 if (wikiTarget instanceof WikiTarget) {
134  40 cacheWikis = getSearchWikis(reference, (WikiTarget) wikiTarget, resolve);
135  543 } else if (wikiTarget instanceof String) {
136  36 cacheWikis = Collections.singleton((String) wikiTarget);
137  507 } else if (wikiTarget instanceof WikiReference) {
138  0 cacheWikis = Collections.singleton(((WikiReference) wikiTarget).getName());
139  507 } else if (wikiTarget instanceof Collection && !((Collection) wikiTarget).isEmpty()) {
140  79 cacheWikis = getSearchWikis(reference, (Collection) wikiTarget, resolve);
141  428 } else if (wikiTarget == null) {
142  428 cacheWikis = getSearchWikis(reference, WikiTarget.ALL, resolve);
143    } else {
144  0 throw new GroupException(
145    "Unsuported wiki target [" + wikiTarget + "] with class [" + wikiTarget.getClass() + "]");
146    }
147   
148  583 return cacheWikis;
149    }
150   
 
151  371 toggle @Override
152    public Collection<DocumentReference> getGroups(DocumentReference reference, Object wikiTarget, boolean recurse)
153    throws GroupException
154    {
155  371 return getGroups(reference, wikiTarget, recurse, null);
156    }
157   
 
158  455 toggle private Collection<DocumentReference> getGroups(DocumentReference reference, Object wikiTarget, boolean recurse,
159    Set<DocumentReference> rootGroups) throws GroupException
160    {
161  455 Collection<String> cacheWikis = getSearchWikis(reference, wikiTarget, false);
162   
163    // Try in the cache
164  455 GroupCacheEntry entry = this.groupsCache.getCacheEntry(reference, cacheWikis, true);
165   
166  455 Collection<DocumentReference> groups = get(entry, recurse);
167  455 if (groups != null) {
168  304 if (rootGroups != null) {
169  13 rootGroups.addAll(groups);
170    }
171   
172  304 return groups;
173    }
174   
175    // Not in the cache
176   
177  151 synchronized (entry) {
178    // Check if it was calculated by another thread in the meantime
179  151 groups = get(entry, recurse);
180  151 if (groups != null) {
181  0 if (rootGroups != null) {
182  0 rootGroups.addAll(groups);
183    }
184   
185  0 return groups;
186    }
187   
188    // Get direct groups
189  151 groups = entry.getDirect();
190  151 if (groups == null) {
191  128 groups = entry.setDirect(getGroups(reference, cacheWikis));
192    }
193   
194    // Get all groups
195  151 if (recurse) {
196  129 Set<DocumentReference> resolvedGroups = new LinkedHashSet<>();
197   
198  129 if (rootGroups == null) {
199  58 rootGroups = resolvedGroups;
200    }
201   
202    // Make sure asked reference won't be resolved
203  129 resolvedGroups.add(reference);
204   
205    // Recursively resolve sub-groups
206  129 for (DocumentReference group : groups) {
207    // Protect against cross references between groups
208  87 if (!rootGroups.contains(group)) {
209  84 rootGroups.add(group);
210  84 resolvedGroups.add(group);
211   
212  84 Collection<DocumentReference> subGRoups = getGroups(group, cacheWikis, true, rootGroups);
213   
214  84 if (subGRoups != null) {
215  81 resolvedGroups.addAll(subGRoups);
216    } else {
217  3 groups = null;
218    }
219    } else {
220  3 groups = null;
221    }
222    }
223   
224    // Remove asked reference from groups
225  129 resolvedGroups.remove(reference);
226   
227  129 if (groups != null || rootGroups == resolvedGroups) {
228  126 groups = entry.setAll(resolvedGroups);
229    }
230    } else {
231  22 if (rootGroups != null) {
232  0 rootGroups.addAll(groups);
233    }
234    }
235   
236  151 return groups;
237    }
238    }
239   
 
240  136 toggle private XWikiGroupService getXWikiGroupService(XWikiContext xcontext) throws GroupException
241    {
242  136 try {
243  136 return xcontext.getWiki().getGroupService(xcontext);
244    } catch (XWikiException e) {
245  0 throw new GroupException("Failed to get group service", e);
246    }
247    }
248   
 
249  128 toggle private Collection<DocumentReference> getGroups(DocumentReference reference, Object wikiTarget)
250    throws GroupException
251    {
252  128 XWikiContext xcontext = this.xcontextProvider.get();
253   
254  128 XWikiGroupService groupService = getXWikiGroupService(xcontext);
255   
256  128 Collection<String> searchWikis = getSearchWikis(reference, wikiTarget, true);
257   
258  128 Set<DocumentReference> groups = new LinkedHashSet<>();
259   
260  128 WikiReference currrentWiki = xcontext.getWikiReference();
261  128 for (String wiki : searchWikis) {
262  165 try {
263  165 xcontext.setWikiId(wiki);
264   
265  165 for (DocumentReference groupReference : groupService.getAllGroupsReferencesForMember(reference, -1, 0,
266    xcontext)) {
267  86 groups.add(this.referenceFactory.getReference(groupReference));
268    }
269    } catch (XWikiException e) {
270  0 throw new GroupException(
271    "Failed to get all groups for member [" + reference + "] in wiki [" + wiki + "]", e);
272    } finally {
273  165 xcontext.setWikiReference(currrentWiki);
274    }
275    }
276   
277  128 return groups;
278    }
279   
 
280  649 toggle private Collection<DocumentReference> get(GroupCacheEntry entry, boolean recurse)
281    {
282  649 Collection<DocumentReference> references;
283   
284  649 if (recurse) {
285  554 references = entry.getAll();
286    } else {
287  95 references = entry.getDirect();
288    }
289   
290  649 return references;
291    }
292   
 
293  24 toggle @Override
294    public Collection<DocumentReference> getMembers(DocumentReference reference, boolean recurse) throws GroupException
295    {
296  24 return getMembers(reference, recurse, null);
297    }
298   
 
299  29 toggle private Collection<DocumentReference> getMembers(DocumentReference reference, boolean recurse,
300    Set<DocumentReference> rootMembers) throws GroupException
301    {
302    // Try in the cache
303  29 GroupCacheEntry entry = this.membersCache.getCacheEntry(reference, true);
304   
305  29 Collection<DocumentReference> members = get(entry, recurse);
306  29 if (members != null) {
307  15 if (rootMembers != null) {
308  1 rootMembers.addAll(members);
309    }
310   
311  15 return members;
312    }
313   
314    // Not in the cache
315   
316  14 synchronized (entry) {
317    // Check if it was calculated by another thread in the meantime
318  14 members = get(entry, recurse);
319  14 if (members != null) {
320  0 if (rootMembers != null) {
321  0 rootMembers.addAll(members);
322    }
323   
324  0 return members;
325    }
326   
327    // Get direct members
328  14 members = entry.getDirect();
329  14 if (members == null) {
330  8 members = entry.setDirect(getMembers(reference));
331    }
332   
333    // Get all members
334  14 if (recurse) {
335  9 Set<DocumentReference> resolvedMembers = new LinkedHashSet<>();
336   
337  9 if (rootMembers == null) {
338  5 rootMembers = resolvedMembers;
339    }
340   
341    // Make sure asked reference won't be resolved
342  9 resolvedMembers.add(reference);
343   
344    // Recursively resolve sub-groups
345  9 for (DocumentReference member : members) {
346    // Protect against cross references between groups
347  6 if (!rootMembers.contains(member)) {
348  5 rootMembers.add(member);
349  5 resolvedMembers.add(member);
350   
351  5 Collection<DocumentReference> subMembers = getMembers(member, true, rootMembers);
352   
353  5 if (subMembers != null) {
354  4 resolvedMembers.addAll(subMembers);
355    } else {
356  1 members = null;
357    }
358    } else {
359  1 members = null;
360    }
361    }
362   
363    // Remove asked reference from members
364  9 resolvedMembers.remove(reference);
365   
366  9 if (members != null || rootMembers == resolvedMembers) {
367  8 members = entry.setAll(resolvedMembers);
368    }
369    } else {
370  5 if (rootMembers != null) {
371  0 rootMembers.addAll(members);
372    }
373    }
374   
375  14 return members;
376    }
377    }
378   
 
379  8 toggle private Collection<DocumentReference> getMembers(DocumentReference reference) throws GroupException
380    {
381  8 XWikiContext xcontext = this.xcontextProvider.get();
382   
383  8 XWikiGroupService groupService = getXWikiGroupService(xcontext);
384   
385  8 Collection<String> memberStrings;
386  8 try {
387  8 memberStrings =
388    groupService.getAllMembersNamesForGroup(this.serializer.serialize(reference), -1, 0, xcontext);
389    } catch (XWikiException e) {
390  0 throw new GroupException("Failed to get members of group [" + reference + "]", e);
391    }
392   
393  8 Set<DocumentReference> members = new LinkedHashSet<>();
394   
395  8 for (String memberString : memberStrings) {
396  5 members.add(this.referenceFactory.getReference(this.resolver.resolve(memberString, reference)));
397    }
398   
399  8 return members;
400    }
401    }