1 |
|
|
2 |
|
|
3 |
|
|
4 |
|
|
5 |
|
|
6 |
|
|
7 |
|
|
8 |
|
|
9 |
|
|
10 |
|
|
11 |
|
|
12 |
|
|
13 |
|
|
14 |
|
|
15 |
|
|
16 |
|
|
17 |
|
|
18 |
|
|
19 |
|
|
20 |
|
package com.xpn.xwiki.internal.plugin.rightsmanager; |
21 |
|
|
22 |
|
import java.util.ArrayDeque; |
23 |
|
import java.util.ArrayList; |
24 |
|
import java.util.Collection; |
25 |
|
import java.util.Collections; |
26 |
|
import java.util.Deque; |
27 |
|
import java.util.Iterator; |
28 |
|
import java.util.LinkedHashSet; |
29 |
|
import java.util.List; |
30 |
|
import java.util.NoSuchElementException; |
31 |
|
|
32 |
|
import org.apache.commons.lang3.StringUtils; |
33 |
|
import org.xwiki.context.Execution; |
34 |
|
import org.xwiki.context.ExecutionContext; |
35 |
|
import org.xwiki.model.reference.DocumentReference; |
36 |
|
import org.xwiki.model.reference.DocumentReferenceResolver; |
37 |
|
import org.xwiki.model.reference.LocalDocumentReference; |
38 |
|
|
39 |
|
import com.xpn.xwiki.XWikiContext; |
40 |
|
import com.xpn.xwiki.XWikiException; |
41 |
|
import com.xpn.xwiki.doc.XWikiDocument; |
42 |
|
import com.xpn.xwiki.objects.BaseObject; |
43 |
|
import com.xpn.xwiki.plugin.rightsmanager.RightsManager; |
44 |
|
import com.xpn.xwiki.user.api.XWikiRightService; |
45 |
|
|
46 |
|
|
47 |
|
|
48 |
|
|
49 |
|
@link |
50 |
|
|
51 |
|
@param@link |
52 |
|
@version |
53 |
|
@since |
54 |
|
@since |
55 |
|
|
|
|
| 92.1% |
Uncovered Elements: 13 (165) |
Complexity: 49 |
Complexity Density: 0.5 |
|
56 |
|
public class UserIterator<T> implements Iterator<T> |
57 |
|
{ |
58 |
|
|
59 |
|
|
60 |
|
|
61 |
|
static final LocalDocumentReference GROUP_CLASS_REF = |
62 |
|
new LocalDocumentReference(RightsManager.DEFAULT_USERORGROUP_SPACE, "XWikiGroups"); |
63 |
|
|
64 |
|
|
65 |
|
|
66 |
|
|
67 |
|
static final LocalDocumentReference USER_CLASS_REF = |
68 |
|
new LocalDocumentReference(RightsManager.DEFAULT_USERORGROUP_SPACE, "XWikiUsers"); |
69 |
|
|
70 |
|
|
71 |
|
private DocumentReferenceResolver<String> explicitDocumentReferenceResolver; |
72 |
|
|
73 |
|
private final Execution execution; |
74 |
|
|
75 |
|
private final XWikiContext xwikiContext; |
76 |
|
|
77 |
|
private List<DocumentReference> userAndGroupReferences; |
78 |
|
|
79 |
|
private List<DocumentReference> excludedUserAndGroupReferences; |
80 |
|
|
81 |
|
private List<DocumentReference> processedGroups = new ArrayList<>(); |
82 |
|
|
83 |
|
private Deque<Iterator<DocumentReference>> userAndGroupIteratorStack = new ArrayDeque<>(); |
84 |
|
|
85 |
|
private T lookaheadValue; |
86 |
|
|
87 |
|
private UserDataExtractor<T> userDataExtractor; |
88 |
|
|
89 |
|
|
90 |
|
|
91 |
|
|
92 |
|
@param |
93 |
|
@param |
94 |
|
@param |
95 |
|
@param |
96 |
|
@link |
97 |
|
@param@link |
98 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (3) |
Complexity: 1 |
Complexity Density: 0.33 |
|
99 |
36 |
public UserIterator(List<DocumentReference> userAndGroupReferences,... |
100 |
|
List<DocumentReference> excludedUserAndGroupReferences, UserDataExtractor<T> userDataExtractor, |
101 |
|
DocumentReferenceResolver<String> explicitDocumentReferenceResolver, Execution execution) |
102 |
|
{ |
103 |
36 |
initialize(userAndGroupReferences, excludedUserAndGroupReferences, userDataExtractor, |
104 |
|
explicitDocumentReferenceResolver); |
105 |
36 |
this.execution = execution; |
106 |
36 |
this.xwikiContext = null; |
107 |
|
} |
108 |
|
|
109 |
|
|
110 |
|
|
111 |
|
|
112 |
|
@param |
113 |
|
@param |
114 |
|
@param |
115 |
|
@link |
116 |
|
@param@link |
117 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (3) |
Complexity: 1 |
Complexity Density: 0.33 |
|
118 |
19 |
public UserIterator(DocumentReference userOrGroupReference, UserDataExtractor<T> userDataExtractor,... |
119 |
|
DocumentReferenceResolver<String> explicitDocumentReferenceResolver, Execution execution) |
120 |
|
{ |
121 |
19 |
initialize(userOrGroupReference, userDataExtractor, explicitDocumentReferenceResolver); |
122 |
19 |
this.execution = execution; |
123 |
19 |
this.xwikiContext = null; |
124 |
|
} |
125 |
|
|
126 |
|
|
127 |
|
|
128 |
|
|
129 |
|
@param |
130 |
|
@param |
131 |
|
@param |
132 |
|
@param |
133 |
|
@link |
134 |
|
@param@link |
135 |
|
|
|
|
| 0% |
Uncovered Elements: 3 (3) |
Complexity: 1 |
Complexity Density: 0.33 |
|
136 |
0 |
public UserIterator(List<DocumentReference> userAndGroupReferences,... |
137 |
|
List<DocumentReference> excludedUserAndGroupReferences, UserDataExtractor<T> userDataExtractor, |
138 |
|
DocumentReferenceResolver<String> explicitDocumentReferenceResolver, XWikiContext xwikiContext) |
139 |
|
{ |
140 |
0 |
initialize(userAndGroupReferences, excludedUserAndGroupReferences, userDataExtractor, |
141 |
|
explicitDocumentReferenceResolver); |
142 |
0 |
this.execution = null; |
143 |
0 |
this.xwikiContext = xwikiContext; |
144 |
|
} |
145 |
|
|
146 |
|
|
147 |
|
|
148 |
|
|
149 |
|
@param |
150 |
|
@param |
151 |
|
@param |
152 |
|
@link |
153 |
|
@param@link |
154 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (3) |
Complexity: 1 |
Complexity Density: 0.33 |
|
155 |
9 |
public UserIterator(DocumentReference userOrGroupReference, UserDataExtractor<T> userDataExtractor,... |
156 |
|
DocumentReferenceResolver<String> explicitDocumentReferenceResolver, XWikiContext xwikiContext) |
157 |
|
{ |
158 |
9 |
initialize(userOrGroupReference, userDataExtractor, explicitDocumentReferenceResolver); |
159 |
9 |
this.execution = null; |
160 |
9 |
this.xwikiContext = xwikiContext; |
161 |
|
} |
162 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (4) |
Complexity: 2 |
Complexity Density: 1 |
|
163 |
28 |
private void initialize(DocumentReference userOrGroupReference, UserDataExtractor<T> userDataExtractor,... |
164 |
|
DocumentReferenceResolver<String> explicitDocumentReferenceResolver) |
165 |
|
{ |
166 |
28 |
List<DocumentReference> references = userOrGroupReference == null |
167 |
|
? Collections.<DocumentReference>emptyList() : Collections.singletonList(userOrGroupReference); |
168 |
28 |
initialize(references, null, userDataExtractor, explicitDocumentReferenceResolver); |
169 |
|
} |
170 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (12) |
Complexity: 4 |
Complexity Density: 0.5 |
|
171 |
64 |
private void initialize(List<DocumentReference> userAndGroupReferences,... |
172 |
|
List<DocumentReference> excludedUserAndGroupReferences, UserDataExtractor<T> userDataExtractor, |
173 |
|
DocumentReferenceResolver<String> explicitDocumentReferenceResolver) |
174 |
|
{ |
175 |
64 |
this.userAndGroupReferences = userAndGroupReferences; |
176 |
64 |
this.excludedUserAndGroupReferences = excludedUserAndGroupReferences; |
177 |
64 |
if (excludedUserAndGroupReferences == null) { |
178 |
59 |
this.excludedUserAndGroupReferences = Collections.emptyList(); |
179 |
|
} |
180 |
64 |
this.explicitDocumentReferenceResolver = explicitDocumentReferenceResolver; |
181 |
64 |
this.userDataExtractor = userDataExtractor; |
182 |
64 |
if (userAndGroupReferences != null && !userAndGroupReferences.isEmpty()) { |
183 |
63 |
this.userAndGroupIteratorStack.push(userAndGroupReferences.iterator()); |
184 |
|
} |
185 |
|
} |
186 |
|
|
|
|
| 80% |
Uncovered Elements: 1 (5) |
Complexity: 2 |
Complexity Density: 0.67 |
|
187 |
92 |
@Override... |
188 |
|
public boolean hasNext() |
189 |
|
{ |
190 |
92 |
if (this.lookaheadValue == null) { |
191 |
92 |
this.lookaheadValue = getNext(); |
192 |
|
} |
193 |
92 |
return this.lookaheadValue != null; |
194 |
|
} |
195 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (11) |
Complexity: 3 |
Complexity Density: 0.43 |
|
196 |
39 |
@Override... |
197 |
|
public T next() |
198 |
|
{ |
199 |
39 |
T currentValue = this.lookaheadValue; |
200 |
39 |
if (currentValue != null) { |
201 |
33 |
this.lookaheadValue = null; |
202 |
|
} else { |
203 |
6 |
currentValue = getNext(); |
204 |
3 |
if (currentValue == null) { |
205 |
1 |
throw new NoSuchElementException(String.format( |
206 |
|
"No more users to extract from the passed references [%s]", serializeUserAndGroupReferences())); |
207 |
|
} |
208 |
|
} |
209 |
35 |
return currentValue; |
210 |
|
} |
211 |
|
|
|
|
| 83.3% |
Uncovered Elements: 2 (12) |
Complexity: 3 |
Complexity Density: 0.38 |
|
212 |
4 |
private String serializeUserAndGroupReferences()... |
213 |
|
{ |
214 |
4 |
StringBuilder buffer = new StringBuilder(); |
215 |
4 |
Iterator<DocumentReference> iterator = this.userAndGroupReferences.iterator(); |
216 |
8 |
while (iterator.hasNext()) { |
217 |
4 |
DocumentReference reference = iterator.next(); |
218 |
4 |
buffer.append('[').append(reference).append(']'); |
219 |
4 |
if (iterator.hasNext()) { |
220 |
0 |
buffer.append(',').append(' '); |
221 |
|
} |
222 |
|
} |
223 |
4 |
return buffer.toString(); |
224 |
|
} |
225 |
|
|
|
|
| 0% |
Uncovered Elements: 1 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
226 |
0 |
@Override... |
227 |
|
public void remove() |
228 |
|
{ |
229 |
0 |
throw new UnsupportedOperationException("remove"); |
230 |
|
} |
231 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (6) |
Complexity: 3 |
Complexity Density: 0.75 |
|
232 |
98 |
private T getNext()... |
233 |
|
{ |
234 |
98 |
T currentValue = null; |
235 |
|
|
236 |
|
|
237 |
|
|
238 |
179 |
while (currentValue == null && !this.userAndGroupIteratorStack.isEmpty()) { |
239 |
84 |
currentValue = getNextUser(this.userAndGroupIteratorStack.peek()); |
240 |
|
} |
241 |
|
|
242 |
95 |
return currentValue; |
243 |
|
} |
244 |
|
|
245 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (20) |
Complexity: 6 |
Complexity Density: 0.5 |
|
246 |
84 |
private T getNextUser(Iterator<DocumentReference> currentIterator)... |
247 |
|
{ |
248 |
84 |
T currentValue = null; |
249 |
|
|
250 |
84 |
DocumentReference currentReference = currentIterator.next(); |
251 |
|
|
252 |
|
|
253 |
84 |
if (!this.excludedUserAndGroupReferences.contains(currentReference)) { |
254 |
|
|
255 |
82 |
if (isSuperAdmin(currentReference)) { |
256 |
2 |
currentValue = this.userDataExtractor.extractFromSuperadmin(currentReference); |
257 |
80 |
} else if (isGuest(currentReference)) { |
258 |
2 |
currentValue = this.userDataExtractor.extractFromGuest(currentReference); |
259 |
|
} else { |
260 |
78 |
XWikiDocument document = getFailsafeDocument(currentReference); |
261 |
|
|
262 |
75 |
if (document != null && !document.isNew()) { |
263 |
73 |
currentValue = handleUserOrGroupReference(currentReference, document); |
264 |
|
} |
265 |
|
} |
266 |
|
} |
267 |
|
|
268 |
81 |
cleanStackIfNeeded(currentIterator); |
269 |
81 |
return currentValue; |
270 |
|
} |
271 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
272 |
82 |
private boolean isSuperAdmin(DocumentReference reference)... |
273 |
|
{ |
274 |
82 |
return reference.getLastSpaceReference().getName().equals(RightsManager.DEFAULT_USERORGROUP_SPACE) |
275 |
|
&& reference.getName().equalsIgnoreCase(XWikiRightService.SUPERADMIN_USER); |
276 |
|
} |
277 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
278 |
80 |
private boolean isGuest(DocumentReference reference)... |
279 |
|
{ |
280 |
80 |
return reference.getLastSpaceReference().getName().equals(RightsManager.DEFAULT_USERORGROUP_SPACE) |
281 |
|
&& reference.getName().equals(XWikiRightService.GUEST_USER); |
282 |
|
} |
283 |
|
|
|
|
| 95.5% |
Uncovered Elements: 1 (22) |
Complexity: 5 |
Complexity Density: 0.36 |
|
284 |
73 |
private T handleUserOrGroupReference(DocumentReference currentReference, XWikiDocument document)... |
285 |
|
{ |
286 |
73 |
T value = null; |
287 |
|
|
288 |
|
|
289 |
73 |
BaseObject userObject = document.getXObject(USER_CLASS_REF); |
290 |
73 |
boolean isUserReference = userObject != null; |
291 |
|
|
292 |
|
|
293 |
|
|
294 |
73 |
List<BaseObject> members = document.getXObjects(GROUP_CLASS_REF); |
295 |
73 |
boolean isGroupReference = members != null && !members.isEmpty(); |
296 |
|
|
297 |
|
|
298 |
73 |
if (isGroupReference) { |
299 |
|
|
300 |
11 |
if (!processedGroups.contains(currentReference)) { |
301 |
10 |
processedGroups.add(currentReference); |
302 |
|
|
303 |
|
|
304 |
10 |
Collection<DocumentReference> groupMemberReferences = |
305 |
|
convertToDocumentReferences(members, currentReference); |
306 |
10 |
if (!groupMemberReferences.isEmpty()) { |
307 |
10 |
this.userAndGroupIteratorStack.push(groupMemberReferences.iterator()); |
308 |
|
} |
309 |
|
} |
310 |
|
} |
311 |
|
|
312 |
73 |
if (isUserReference) { |
313 |
59 |
value = this.userDataExtractor.extract(currentReference, document, userObject); |
314 |
|
} |
315 |
|
|
316 |
73 |
return value; |
317 |
|
} |
318 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (4) |
Complexity: 3 |
Complexity Density: 1.5 |
|
319 |
81 |
private void cleanStackIfNeeded(Iterator<DocumentReference> currentIterator)... |
320 |
|
{ |
321 |
|
|
322 |
150 |
while (!this.userAndGroupIteratorStack.isEmpty() && !this.userAndGroupIteratorStack.peek().hasNext()) { |
323 |
69 |
this.userAndGroupIteratorStack.pop(); |
324 |
|
} |
325 |
|
} |
326 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (3) |
Complexity: 2 |
Complexity Density: 0.67 |
|
327 |
78 |
private XWikiDocument getFailsafeDocument(DocumentReference reference)... |
328 |
|
{ |
329 |
78 |
try { |
330 |
78 |
return getXwikiContext().getWiki().getDocument(reference, getXwikiContext()); |
331 |
|
} catch (XWikiException e) { |
332 |
1 |
throw new RuntimeException(String.format("Failed to get document for User or Group [%s] when extracting " |
333 |
|
+ "all users for the references [%s]", reference, serializeUserAndGroupReferences()), e); |
334 |
|
} |
335 |
|
} |
336 |
|
|
|
|
| 82.4% |
Uncovered Elements: 3 (17) |
Complexity: 4 |
Complexity Density: 0.36 |
|
337 |
10 |
private Collection<DocumentReference> convertToDocumentReferences(List<BaseObject> memberObjects,... |
338 |
|
DocumentReference currentReference) |
339 |
|
{ |
340 |
|
|
341 |
10 |
Collection<DocumentReference> members = new LinkedHashSet<>(); |
342 |
10 |
for (BaseObject memberObject : memberObjects) { |
343 |
|
|
344 |
20 |
if (memberObject == null) { |
345 |
0 |
continue; |
346 |
|
} |
347 |
|
|
348 |
20 |
String member = memberObject.getStringValue("member"); |
349 |
|
|
350 |
|
|
351 |
20 |
if (StringUtils.isBlank(member)) { |
352 |
1 |
continue; |
353 |
|
} |
354 |
|
|
355 |
19 |
DocumentReference resolvedReference = |
356 |
|
this.explicitDocumentReferenceResolver.resolve(member, currentReference); |
357 |
19 |
if (!resolvedReference.equals(currentReference)) { |
358 |
19 |
members.add(resolvedReference); |
359 |
|
} |
360 |
|
} |
361 |
10 |
return members; |
362 |
|
} |
363 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (15) |
Complexity: 5 |
Complexity Density: 0.56 |
|
364 |
154 |
protected XWikiContext getXwikiContext()... |
365 |
|
{ |
366 |
154 |
if (execution == null) { |
367 |
16 |
return this.xwikiContext; |
368 |
|
} |
369 |
|
|
370 |
138 |
XWikiContext context = null; |
371 |
138 |
ExecutionContext executionContext = execution.getContext(); |
372 |
138 |
if (executionContext != null) { |
373 |
137 |
context = (XWikiContext) executionContext.getProperty(XWikiContext.EXECUTIONCONTEXT_KEY); |
374 |
|
} |
375 |
138 |
if (executionContext == null || context == null) { |
376 |
2 |
throw new RuntimeException(String.format("Aborting member extraction from passed references [%s] since " |
377 |
|
+ "no XWiki Context was found", serializeUserAndGroupReferences())); |
378 |
|
} |
379 |
136 |
return context; |
380 |
|
} |
381 |
|
} |