1 |
|
|
2 |
|
|
3 |
|
|
4 |
|
|
5 |
|
|
6 |
|
|
7 |
|
|
8 |
|
|
9 |
|
|
10 |
|
|
11 |
|
|
12 |
|
|
13 |
|
|
14 |
|
|
15 |
|
|
16 |
|
|
17 |
|
|
18 |
|
|
19 |
|
|
20 |
|
package org.xwiki.security.authorization.cache.internal; |
21 |
|
|
22 |
|
import java.util.ArrayDeque; |
23 |
|
import java.util.ArrayList; |
24 |
|
import java.util.Arrays; |
25 |
|
import java.util.Collection; |
26 |
|
import java.util.Deque; |
27 |
|
import java.util.HashSet; |
28 |
|
import java.util.concurrent.locks.Lock; |
29 |
|
import java.util.concurrent.locks.ReadWriteLock; |
30 |
|
import java.util.concurrent.locks.ReentrantReadWriteLock; |
31 |
|
|
32 |
|
import javax.inject.Inject; |
33 |
|
import javax.inject.Singleton; |
34 |
|
|
35 |
|
import org.slf4j.Logger; |
36 |
|
import org.xwiki.cache.Cache; |
37 |
|
import org.xwiki.cache.CacheManager; |
38 |
|
import org.xwiki.cache.DisposableCacheValue; |
39 |
|
import org.xwiki.cache.config.CacheConfiguration; |
40 |
|
import org.xwiki.cache.eviction.LRUEvictionConfiguration; |
41 |
|
import org.xwiki.component.annotation.Component; |
42 |
|
import org.xwiki.component.phase.Initializable; |
43 |
|
import org.xwiki.component.phase.InitializationException; |
44 |
|
import org.xwiki.model.reference.EntityReferenceSerializer; |
45 |
|
import org.xwiki.security.GroupSecurityReference; |
46 |
|
import org.xwiki.security.SecurityReference; |
47 |
|
import org.xwiki.security.UserSecurityReference; |
48 |
|
import org.xwiki.security.authorization.SecurityAccessEntry; |
49 |
|
import org.xwiki.security.authorization.SecurityEntry; |
50 |
|
import org.xwiki.security.authorization.SecurityRuleEntry; |
51 |
|
import org.xwiki.security.authorization.cache.ConflictingInsertionException; |
52 |
|
import org.xwiki.security.authorization.cache.ParentEntryEvictedException; |
53 |
|
import org.xwiki.security.authorization.cache.SecurityShadowEntry; |
54 |
|
|
55 |
|
|
56 |
|
|
57 |
|
|
58 |
|
@version |
59 |
|
@since |
60 |
|
|
61 |
|
@Component |
62 |
|
@Singleton |
|
|
| 90.8% |
Uncovered Elements: 23 (249) |
Complexity: 73 |
Complexity Density: 0.49 |
|
63 |
|
public class DefaultSecurityCache implements SecurityCache, Initializable |
64 |
|
{ |
65 |
|
|
66 |
|
private static final int DEFAULT_CAPACITY = 10000; |
67 |
|
|
68 |
|
|
69 |
|
private static final String KEY_CACHE_SEPARATOR = "@@"; |
70 |
|
|
71 |
|
|
72 |
|
@Inject |
73 |
|
private Logger logger; |
74 |
|
|
75 |
|
|
76 |
|
private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(true); |
77 |
|
|
78 |
|
|
79 |
|
private final Lock readLock = readWriteLock.readLock(); |
80 |
|
|
81 |
|
|
82 |
|
private final Lock writeLock = readWriteLock.writeLock(); |
83 |
|
|
84 |
|
@link |
85 |
|
@Inject |
86 |
|
private EntityReferenceSerializer<String> keySerializer; |
87 |
|
|
88 |
|
|
89 |
|
@Inject |
90 |
|
private CacheManager cacheManager; |
91 |
|
|
92 |
|
|
93 |
|
private Cache<SecurityCacheEntry> cache; |
94 |
|
|
95 |
|
|
96 |
|
private SecurityCacheEntry newEntry; |
97 |
|
|
98 |
|
|
99 |
|
@return |
100 |
|
@throws |
101 |
|
|
|
|
| 87.5% |
Uncovered Elements: 1 (8) |
Complexity: 2 |
Complexity Density: 0.25 |
|
102 |
202 |
private Cache<SecurityCacheEntry> newCache() throws InitializationException... |
103 |
|
{ |
104 |
202 |
CacheConfiguration cacheConfig = new CacheConfiguration(); |
105 |
202 |
cacheConfig.setConfigurationId("platform.security.authorization.cache"); |
106 |
202 |
LRUEvictionConfiguration lru = new LRUEvictionConfiguration(); |
107 |
202 |
lru.setMaxEntries(DEFAULT_CAPACITY); |
108 |
202 |
cacheConfig.put(LRUEvictionConfiguration.CONFIGURATIONID, lru); |
109 |
202 |
try { |
110 |
202 |
return cacheManager.createNewCache(cacheConfig); |
111 |
|
} catch (Exception e) { |
112 |
0 |
throw new InitializationException( |
113 |
|
String.format("Unable to create the security cache with a capacity of [%d] entries", |
114 |
|
lru.getMaxEntries()), e); |
115 |
|
} |
116 |
|
} |
117 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
118 |
202 |
@Override... |
119 |
|
public void initialize() throws InitializationException |
120 |
|
{ |
121 |
202 |
cache = newCache(); |
122 |
|
} |
123 |
|
|
124 |
|
|
125 |
|
|
126 |
|
|
|
|
| 78.8% |
Uncovered Elements: 40 (189) |
Complexity: 56 |
Complexity Density: 0.51 |
|
127 |
|
private class SecurityCacheEntry implements DisposableCacheValue |
128 |
|
{ |
129 |
|
|
130 |
|
|
131 |
|
|
132 |
|
private SecurityEntry entry; |
133 |
|
|
134 |
|
|
135 |
|
|
136 |
|
|
137 |
|
private Collection<SecurityCacheEntry> parents; |
138 |
|
|
139 |
|
|
140 |
|
|
141 |
|
|
142 |
|
private Collection<SecurityCacheEntry> children; |
143 |
|
|
144 |
|
|
145 |
|
|
146 |
|
|
147 |
|
private boolean disposed; |
148 |
|
|
149 |
|
|
150 |
|
|
151 |
|
@param |
152 |
|
@throws |
153 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (15) |
Complexity: 3 |
Complexity Density: 0.27 |
|
154 |
2268 |
SecurityCacheEntry(SecurityRuleEntry entry) throws ParentEntryEvictedException... |
155 |
|
{ |
156 |
2268 |
this.entry = entry; |
157 |
2268 |
SecurityReference parentReference = entry.getReference().getParentSecurityReference(); |
158 |
2268 |
if (parentReference != null) { |
159 |
2108 |
SecurityCacheEntry parent = DefaultSecurityCache.this.getEntry(parentReference); |
160 |
2108 |
if (parent == null) { |
161 |
1 |
throw new ParentEntryEvictedException(); |
162 |
|
} |
163 |
2107 |
this.parents = Arrays.asList(parent); |
164 |
2107 |
parent.addChild(this); |
165 |
2107 |
logNewEntry(); |
166 |
|
} else { |
167 |
160 |
this.parents = null; |
168 |
160 |
logNewEntry(); |
169 |
|
} |
170 |
|
|
171 |
|
} |
172 |
|
|
173 |
|
|
174 |
|
|
175 |
|
@param |
176 |
|
@throws |
177 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (11) |
Complexity: 3 |
Complexity Density: 0.33 |
|
178 |
44 |
SecurityCacheEntry(SecurityShadowEntry entry) throws ParentEntryEvictedException... |
179 |
|
{ |
180 |
44 |
this.entry = entry; |
181 |
44 |
SecurityCacheEntry parent1 = DefaultSecurityCache.this.getEntry(entry.getReference()); |
182 |
44 |
SecurityCacheEntry parent2 = DefaultSecurityCache.this.getEntry(entry.getWikiReference()); |
183 |
44 |
if (parent1 == null || parent2 == null) { |
184 |
2 |
throw new ParentEntryEvictedException(); |
185 |
|
} |
186 |
42 |
this.parents = Arrays.asList(parent1, parent2); |
187 |
42 |
parent1.addChild(this); |
188 |
42 |
parent2.addChild(this); |
189 |
42 |
logNewEntry(); |
190 |
|
} |
191 |
|
|
192 |
|
|
193 |
|
|
194 |
|
@param |
195 |
|
@throws |
196 |
|
|
|
|
| 0% |
Uncovered Elements: 1 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
197 |
0 |
SecurityCacheEntry(SecurityAccessEntry entry) throws ParentEntryEvictedException... |
198 |
|
{ |
199 |
0 |
this(entry, null); |
200 |
|
} |
201 |
|
|
202 |
|
|
203 |
|
|
204 |
|
@param |
205 |
|
@param |
206 |
|
@throws |
207 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (21) |
Complexity: 7 |
Complexity Density: 0.64 |
|
208 |
2642 |
SecurityCacheEntry(SecurityAccessEntry entry, SecurityReference wiki) throws ParentEntryEvictedException... |
209 |
|
{ |
210 |
2642 |
this.entry = entry; |
211 |
2642 |
boolean isSelf = entry.getReference().equals(entry.getUserReference()); |
212 |
2642 |
SecurityCacheEntry parent1 = DefaultSecurityCache.this.getEntry(entry.getReference()); |
213 |
2642 |
SecurityCacheEntry parent2 = (isSelf) ? parent1 |
214 |
2495 |
: (wiki != null) ? DefaultSecurityCache.this.getShadowEntry(entry.getUserReference(), wiki) |
215 |
|
: DefaultSecurityCache.this.getEntry(entry.getUserReference()); |
216 |
2642 |
if (parent1 == null || parent2 == null) { |
217 |
2 |
throw new ParentEntryEvictedException(); |
218 |
|
} |
219 |
2640 |
this.parents = (isSelf) ? Arrays.asList(parent1) : Arrays.asList(parent1, parent2); |
220 |
2640 |
parent1.addChild(this); |
221 |
2640 |
if (!isSelf) { |
222 |
2493 |
parent2.addChild(this); |
223 |
|
} |
224 |
2640 |
logNewEntry(); |
225 |
|
} |
226 |
|
|
227 |
|
|
228 |
|
|
229 |
|
@param |
230 |
|
@param |
231 |
|
@throws |
232 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
233 |
195 |
SecurityCacheEntry(SecurityRuleEntry entry, Collection<GroupSecurityReference> groups)... |
234 |
|
throws ParentEntryEvictedException |
235 |
|
{ |
236 |
195 |
this(entry, groups, entry.getReference().getParentSecurityReference()); |
237 |
|
} |
238 |
|
|
239 |
|
|
240 |
|
|
241 |
|
@param |
242 |
|
@param |
243 |
|
@throws |
244 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
245 |
58 |
SecurityCacheEntry(SecurityShadowEntry entry, Collection<GroupSecurityReference> groups)... |
246 |
|
throws ParentEntryEvictedException |
247 |
|
{ |
248 |
58 |
this(entry, groups, entry.getReference()); |
249 |
|
} |
250 |
|
|
251 |
|
|
252 |
|
|
253 |
|
@param |
254 |
|
@param |
255 |
|
@param |
256 |
|
@throws |
257 |
|
|
|
|
| 68.2% |
Uncovered Elements: 7 (22) |
Complexity: 5 |
Complexity Density: 0.36 |
|
258 |
254 |
private SecurityCacheEntry(SecurityEntry entry, Collection<GroupSecurityReference> groups,... |
259 |
|
SecurityReference parentReference) |
260 |
|
throws ParentEntryEvictedException |
261 |
|
{ |
262 |
254 |
this.entry = entry; |
263 |
254 |
int parentSize = groups.size() + ((parentReference == null) ? 0 : 1); |
264 |
254 |
if (parentSize > 0) { |
265 |
254 |
this.parents = new ArrayList<SecurityCacheEntry>(parentSize); |
266 |
254 |
if (parentReference != null) { |
267 |
254 |
SecurityCacheEntry parent = DefaultSecurityCache.this.getEntry(parentReference); |
268 |
254 |
if (parent == null) { |
269 |
0 |
throw new ParentEntryEvictedException(); |
270 |
|
} |
271 |
254 |
this.parents.add(parent); |
272 |
254 |
parent.addChild(this); |
273 |
|
} |
274 |
254 |
addParentGroups(groups, parentReference); |
275 |
253 |
logNewEntry(); |
276 |
|
} else { |
277 |
0 |
this.parents = null; |
278 |
0 |
logNewEntry(); |
279 |
|
} |
280 |
|
} |
281 |
|
|
282 |
|
|
283 |
|
|
284 |
|
|
285 |
|
@param |
286 |
|
@param |
287 |
|
@throws |
288 |
|
|
|
|
| 85.7% |
Uncovered Elements: 2 (14) |
Complexity: 5 |
Complexity Density: 0.62 |
|
289 |
276 |
private void addParentGroups(Collection<GroupSecurityReference> groups,... |
290 |
|
SecurityReference parentReference) throws ParentEntryEvictedException |
291 |
|
{ |
292 |
276 |
for (GroupSecurityReference group : groups) { |
293 |
171 |
if (group.equals(parentReference)) { |
294 |
0 |
continue; |
295 |
|
} |
296 |
171 |
SecurityCacheEntry parent = (entry instanceof SecurityShadowEntry && group.isGlobal()) |
297 |
|
? DefaultSecurityCache.this.getShadowEntry(group, |
298 |
|
((SecurityShadowEntry) entry).getWikiReference()) |
299 |
|
: DefaultSecurityCache.this.getEntry(group); |
300 |
171 |
if (parent == null) { |
301 |
1 |
throw new ParentEntryEvictedException(); |
302 |
|
} |
303 |
170 |
this.parents.add(parent); |
304 |
170 |
parent.addChild(this); |
305 |
|
} |
306 |
|
} |
307 |
|
|
308 |
|
|
309 |
|
|
310 |
|
|
311 |
|
@param |
312 |
|
@throws |
313 |
|
|
|
|
| 82.4% |
Uncovered Elements: 3 (17) |
Complexity: 6 |
Complexity Density: 0.55 |
|
314 |
271 |
boolean updateParentGroups(Collection<GroupSecurityReference> groups)... |
315 |
|
throws ParentEntryEvictedException |
316 |
|
{ |
317 |
271 |
if (isUser() || !(entry instanceof SecurityRuleEntry)) { |
318 |
228 |
return false; |
319 |
|
} |
320 |
|
|
321 |
43 |
if (groups != null && !groups.isEmpty()) { |
322 |
22 |
if (this.parents == null) { |
323 |
0 |
this.parents = new ArrayList<SecurityCacheEntry>(groups.size()); |
324 |
0 |
addParentGroups(groups, null); |
325 |
|
} else { |
326 |
22 |
SecurityCacheEntry parent = this.parents.iterator().next(); |
327 |
22 |
this.parents = new ArrayList<SecurityCacheEntry>(groups.size() + 1); |
328 |
22 |
this.parents.add(parent); |
329 |
22 |
addParentGroups(groups, parent.entry.getReference()); |
330 |
|
} |
331 |
|
} |
332 |
|
|
333 |
43 |
return true; |
334 |
|
} |
335 |
|
|
336 |
|
|
337 |
|
|
338 |
|
|
|
|
| 10% |
Uncovered Elements: 18 (20) |
Complexity: 5 |
Complexity Density: 0.36 |
|
339 |
5202 |
private void logNewEntry()... |
340 |
|
{ |
341 |
5202 |
if (logger.isDebugEnabled()) { |
342 |
0 |
if (parents == null || parents.size() == 0) { |
343 |
0 |
logger.debug("New orphan entry [{}].", getKey()); |
344 |
0 |
return; |
345 |
|
} |
346 |
0 |
StringBuilder sb = new StringBuilder("New entry ["); |
347 |
0 |
sb.append(getKey()).append("] as child of "); |
348 |
0 |
boolean first = true; |
349 |
0 |
for (SecurityCacheEntry parent : parents) { |
350 |
0 |
if (!first) { |
351 |
0 |
sb.append(", "); |
352 |
|
} else { |
353 |
0 |
first = false; |
354 |
|
} |
355 |
0 |
sb.append('[').append(parent.getKey()).append(']'); |
356 |
|
} |
357 |
0 |
sb.append("."); |
358 |
0 |
logger.debug(sb.toString()); |
359 |
|
} |
360 |
|
} |
361 |
|
|
362 |
|
|
363 |
|
@return |
364 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
365 |
143487 |
SecurityEntry getEntry()... |
366 |
|
{ |
367 |
143487 |
return this.entry; |
368 |
|
} |
369 |
|
|
370 |
|
|
371 |
|
@return |
372 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
373 |
2956 |
String getKey()... |
374 |
|
{ |
375 |
2956 |
return DefaultSecurityCache.this.getEntryKey(entry); |
376 |
|
} |
377 |
|
|
378 |
|
|
379 |
|
|
380 |
|
|
381 |
|
|
382 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (6) |
Complexity: 2 |
Complexity Density: 0.5 |
|
383 |
5589 |
@Override... |
384 |
|
public void dispose() |
385 |
|
{ |
386 |
5589 |
if (!disposed) { |
387 |
2963 |
disposed = true; |
388 |
2963 |
disconnectFromParents(); |
389 |
2963 |
disposeChildren(); |
390 |
|
} |
391 |
|
} |
392 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (8) |
Complexity: 3 |
Complexity Density: 0.75 |
|
393 |
2963 |
protected void disconnectFromParents()... |
394 |
|
{ |
395 |
2963 |
if (parents != null) { |
396 |
2868 |
for (SecurityCacheEntry parent : parents) { |
397 |
4610 |
if (!parent.disposed) { |
398 |
1384 |
parent.removeChild(this); |
399 |
|
} |
400 |
|
} |
401 |
|
} |
402 |
|
} |
403 |
|
|
|
|
| 72.2% |
Uncovered Elements: 5 (18) |
Complexity: 6 |
Complexity Density: 0.6 |
|
404 |
2963 |
private void disposeChildren()... |
405 |
|
{ |
406 |
2963 |
if (children != null) { |
407 |
931 |
for (SecurityCacheEntry child : children) { |
408 |
3226 |
if (!child.disposed) { |
409 |
2682 |
if (logger.isDebugEnabled()) { |
410 |
0 |
logger.debug("Cascaded removal of entry [{}] from cache.", child.getKey()); |
411 |
|
} |
412 |
|
|
413 |
2682 |
if (child == newEntry) { |
414 |
0 |
child.dispose(); |
415 |
|
} else { |
416 |
2682 |
try { |
417 |
2682 |
DefaultSecurityCache.this.cache.remove(child.getKey()); |
418 |
|
} catch (Throwable e) { |
419 |
0 |
logger.error("Security cache failure during eviction of entry [{}]", child.getKey(), e); |
420 |
|
} |
421 |
|
} |
422 |
|
} |
423 |
|
} |
424 |
|
} |
425 |
|
} |
426 |
|
|
427 |
|
|
428 |
|
|
429 |
|
@param |
430 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (5) |
Complexity: 2 |
Complexity Density: 0.67 |
|
431 |
7748 |
private void addChild(SecurityCacheEntry entry)... |
432 |
|
{ |
433 |
7748 |
if (this.children == null) { |
434 |
1979 |
this.children = new ArrayList<SecurityCacheEntry>(); |
435 |
|
} |
436 |
7748 |
this.children.add(entry); |
437 |
|
} |
438 |
|
|
439 |
|
|
440 |
|
|
441 |
|
@param |
442 |
|
|
|
|
| 62.5% |
Uncovered Elements: 3 (8) |
Complexity: 3 |
Complexity Density: 0.75 |
|
443 |
1384 |
private void removeChild(SecurityCacheEntry entry)... |
444 |
|
{ |
445 |
1384 |
if (this.children != null) { |
446 |
1384 |
this.children.remove(entry); |
447 |
1384 |
if (logger.isDebugEnabled()) { |
448 |
0 |
logger.debug("Remove child [{}] from [{}].", entry.getKey(), getKey()); |
449 |
|
} |
450 |
|
} |
451 |
|
} |
452 |
|
|
453 |
|
|
454 |
|
@return |
455 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
456 |
2599 |
public boolean isUser()... |
457 |
|
{ |
458 |
2599 |
return entry.getReference() instanceof UserSecurityReference && !(entry instanceof SecurityAccessEntry); |
459 |
|
} |
460 |
|
} |
461 |
|
|
462 |
|
|
463 |
|
@param |
464 |
|
@return |
465 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
466 |
100454 |
private String getEntryKey(SecurityReference reference)... |
467 |
|
{ |
468 |
100454 |
return keySerializer.serialize(reference); |
469 |
|
} |
470 |
|
|
471 |
|
|
472 |
|
@param |
473 |
|
@param |
474 |
|
@return |
475 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
476 |
65005 |
private String getEntryKey(UserSecurityReference userReference, SecurityReference reference)... |
477 |
|
{ |
478 |
65005 |
return keySerializer.serialize(userReference) |
479 |
|
+ KEY_CACHE_SEPARATOR + keySerializer.serialize(reference); |
480 |
|
} |
481 |
|
|
482 |
|
|
483 |
|
@param |
484 |
|
@param |
485 |
|
@return |
486 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
487 |
442 |
private String getShadowEntryKey(SecurityReference userReference, SecurityReference root)... |
488 |
|
{ |
489 |
442 |
return keySerializer.serialize(root) + KEY_CACHE_SEPARATOR + keySerializer.serialize(userReference); |
490 |
|
} |
491 |
|
|
492 |
|
|
493 |
|
@param@link |
494 |
|
@link |
495 |
|
@return |
496 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (9) |
Complexity: 3 |
Complexity Density: 0.6 |
|
497 |
5589 |
private String getEntryKey(SecurityEntry entry)... |
498 |
|
{ |
499 |
5589 |
if (entry instanceof SecurityAccessEntry) { |
500 |
1741 |
return getEntryKey((SecurityAccessEntry) entry); |
501 |
3848 |
} else if (entry instanceof SecurityRuleEntry) { |
502 |
3714 |
return getEntryKey((SecurityRuleEntry) entry); |
503 |
|
} else { |
504 |
133 |
return getEntryKey((SecurityShadowEntry) entry); |
505 |
|
} |
506 |
|
} |
507 |
|
|
508 |
|
|
509 |
|
@param@link |
510 |
|
@link |
511 |
|
@return |
512 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
513 |
133 |
private String getEntryKey(SecurityShadowEntry entry)... |
514 |
|
{ |
515 |
133 |
return getShadowEntryKey(entry.getReference(), entry.getWikiReference()); |
516 |
|
} |
517 |
|
|
518 |
|
|
519 |
|
@param |
520 |
|
@return |
521 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
522 |
3713 |
private String getEntryKey(SecurityRuleEntry entry)... |
523 |
|
{ |
524 |
3714 |
return getEntryKey(entry.getReference()); |
525 |
|
} |
526 |
|
|
527 |
|
|
528 |
|
@param |
529 |
|
@return |
530 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
531 |
4589 |
private String getEntryKey(SecurityAccessEntry entry)... |
532 |
|
{ |
533 |
4589 |
return getEntryKey(entry.getUserReference(), entry.getReference()); |
534 |
|
} |
535 |
|
|
536 |
|
|
537 |
|
@param |
538 |
|
@return |
539 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (4) |
Complexity: 1 |
Complexity Density: 0.25 |
|
540 |
96740 |
private SecurityCacheEntry getEntry(SecurityReference reference)... |
541 |
|
{ |
542 |
96739 |
readLock.lock(); |
543 |
96740 |
try { |
544 |
96740 |
return cache.get(getEntryKey(reference)); |
545 |
|
} finally { |
546 |
96740 |
readLock.unlock(); |
547 |
|
} |
548 |
|
} |
549 |
|
|
550 |
|
|
551 |
|
@param |
552 |
|
@param |
553 |
|
@return |
554 |
|
|
555 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (4) |
Complexity: 1 |
Complexity Density: 0.25 |
|
556 |
60416 |
private SecurityCacheEntry getEntry(UserSecurityReference userReference, SecurityReference reference)... |
557 |
|
{ |
558 |
60416 |
readLock.lock(); |
559 |
60416 |
try { |
560 |
60416 |
return cache.get(getEntryKey(userReference, reference)); |
561 |
|
} finally { |
562 |
60416 |
readLock.unlock(); |
563 |
|
} |
564 |
|
} |
565 |
|
|
566 |
|
|
567 |
|
@param |
568 |
|
@param |
569 |
|
@return |
570 |
|
|
571 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (4) |
Complexity: 1 |
Complexity Density: 0.25 |
|
572 |
309 |
private SecurityCacheEntry getShadowEntry(SecurityReference userReference, SecurityReference wiki)... |
573 |
|
{ |
574 |
309 |
readLock.lock(); |
575 |
309 |
try { |
576 |
309 |
return cache.get(getShadowEntryKey(userReference, wiki)); |
577 |
|
} finally { |
578 |
309 |
readLock.unlock(); |
579 |
|
} |
580 |
|
} |
581 |
|
|
582 |
|
|
583 |
|
@param |
584 |
|
@param |
585 |
|
@return |
586 |
|
@throws |
587 |
|
|
|
|
| 66.7% |
Uncovered Elements: 1 (3) |
Complexity: 2 |
Complexity Density: 0.67 |
|
588 |
2848 |
private boolean isAlreadyInserted(String key, SecurityEntry entry) throws ConflictingInsertionException... |
589 |
|
{ |
590 |
2848 |
try { |
591 |
2848 |
return isAlreadyInserted(key, entry, null); |
592 |
|
} catch (ParentEntryEvictedException e) { |
593 |
|
|
594 |
0 |
return true; |
595 |
|
} |
596 |
|
} |
597 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (14) |
Complexity: 4 |
Complexity Density: 0.5 |
|
598 |
5481 |
private boolean isAlreadyInserted(String key, SecurityEntry entry, Collection<GroupSecurityReference> groups)... |
599 |
|
throws ConflictingInsertionException, ParentEntryEvictedException |
600 |
|
{ |
601 |
5481 |
SecurityCacheEntry oldEntry = cache.get(key); |
602 |
5481 |
if (oldEntry != null) { |
603 |
273 |
if (!oldEntry.getEntry().equals(entry)) { |
604 |
|
|
605 |
2 |
throw new ConflictingInsertionException(); |
606 |
|
} |
607 |
|
|
608 |
271 |
if (oldEntry.updateParentGroups(groups)) { |
609 |
|
|
610 |
43 |
oldEntry.entry = entry; |
611 |
|
} |
612 |
|
|
613 |
271 |
return true; |
614 |
|
} |
615 |
|
|
616 |
5208 |
return false; |
617 |
|
} |
618 |
|
|
619 |
|
|
620 |
|
|
621 |
|
|
622 |
|
@param |
623 |
|
@param |
624 |
|
@throws |
625 |
|
|
626 |
|
|
|
|
| 66.7% |
Uncovered Elements: 3 (9) |
Complexity: 2 |
Complexity Density: 0.29 |
|
627 |
5202 |
private void addEntry(String key, SecurityCacheEntry entry) throws ConflictingInsertionException... |
628 |
|
{ |
629 |
5202 |
try { |
630 |
5202 |
newEntry = entry; |
631 |
5202 |
cache.set(key, newEntry); |
632 |
5202 |
if (entry.disposed) { |
633 |
|
|
634 |
|
|
635 |
0 |
cache.remove(key); |
636 |
0 |
throw new ConflictingInsertionException(); |
637 |
|
} |
638 |
|
} finally { |
639 |
5202 |
newEntry = null; |
640 |
|
} |
641 |
|
} |
642 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
643 |
2258 |
@Override... |
644 |
|
public void add(SecurityRuleEntry entry) |
645 |
|
throws ParentEntryEvictedException, ConflictingInsertionException |
646 |
|
{ |
647 |
2258 |
add(entry, null); |
648 |
|
} |
649 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
650 |
2527 |
@Override... |
651 |
|
public void add(SecurityRuleEntry entry, Collection<GroupSecurityReference> groups) |
652 |
|
throws ConflictingInsertionException, ParentEntryEvictedException |
653 |
|
{ |
654 |
2530 |
add((SecurityEntry) entry, groups); |
655 |
|
} |
656 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
657 |
103 |
@Override... |
658 |
|
public void add(SecurityShadowEntry entry, Collection<GroupSecurityReference> groups) |
659 |
|
throws ConflictingInsertionException, ParentEntryEvictedException |
660 |
|
{ |
661 |
103 |
add((SecurityEntry) entry, groups); |
662 |
|
} |
663 |
|
|
664 |
|
|
665 |
|
|
666 |
|
@param |
667 |
|
@param |
668 |
|
@exception |
669 |
|
|
670 |
|
|
671 |
|
@link |
672 |
|
@throws |
673 |
|
|
674 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (10) |
Complexity: 2 |
Complexity Density: 0.25 |
|
675 |
2630 |
private void add(SecurityEntry entry, Collection<GroupSecurityReference> groups)... |
676 |
|
throws ConflictingInsertionException, ParentEntryEvictedException |
677 |
|
{ |
678 |
2630 |
String key = getEntryKey(entry); |
679 |
|
|
680 |
2633 |
writeLock.lock(); |
681 |
2633 |
try { |
682 |
2632 |
if (isAlreadyInserted(key, entry, groups)) { |
683 |
66 |
return; |
684 |
|
} |
685 |
2566 |
addEntry(key, newSecurityCacheEntry(entry, groups)); |
686 |
|
|
687 |
2562 |
logger.debug("Added rule/shadow entry [{}] into the cache.", key); |
688 |
|
} finally { |
689 |
2633 |
writeLock.unlock(); |
690 |
|
} |
691 |
|
} |
692 |
|
|
693 |
|
|
694 |
|
|
695 |
|
@param |
696 |
|
@param |
697 |
|
@return |
698 |
|
@exception |
699 |
|
|
700 |
|
|
701 |
|
@link |
702 |
|
@throws |
703 |
|
|
704 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (9) |
Complexity: 4 |
Complexity Density: 1.33 |
|
705 |
2566 |
private SecurityCacheEntry newSecurityCacheEntry(SecurityEntry entry, Collection<GroupSecurityReference> groups)... |
706 |
|
throws ConflictingInsertionException, ParentEntryEvictedException |
707 |
|
{ |
708 |
2566 |
if (entry instanceof SecurityRuleEntry) { |
709 |
2464 |
return (groups == null) |
710 |
|
? new SecurityCacheEntry((SecurityRuleEntry) entry) |
711 |
|
: new SecurityCacheEntry((SecurityRuleEntry) entry, groups); |
712 |
|
} else { |
713 |
102 |
return (groups == null) |
714 |
|
? new SecurityCacheEntry((SecurityShadowEntry) entry) |
715 |
|
: new SecurityCacheEntry((SecurityShadowEntry) entry, groups); |
716 |
|
} |
717 |
|
} |
718 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
719 |
269 |
@Override... |
720 |
|
public void add(SecurityAccessEntry entry) |
721 |
|
throws ParentEntryEvictedException, ConflictingInsertionException |
722 |
|
{ |
723 |
269 |
internalAdd(entry, null); |
724 |
|
} |
725 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
726 |
2579 |
@Override... |
727 |
|
public void add(SecurityAccessEntry entry, SecurityReference wiki) |
728 |
|
throws ParentEntryEvictedException, ConflictingInsertionException |
729 |
|
{ |
730 |
2579 |
internalAdd(entry, wiki); |
731 |
|
} |
732 |
|
|
733 |
|
|
734 |
|
|
735 |
|
@param |
736 |
|
@param |
737 |
|
@throws |
738 |
|
|
739 |
|
|
740 |
|
@link |
741 |
|
@throws |
742 |
|
|
743 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (11) |
Complexity: 2 |
Complexity Density: 0.22 |
|
744 |
2848 |
private void internalAdd(SecurityAccessEntry entry, SecurityReference wiki)... |
745 |
|
throws ParentEntryEvictedException, ConflictingInsertionException |
746 |
|
{ |
747 |
2848 |
String key = getEntryKey(entry); |
748 |
|
|
749 |
2848 |
writeLock.lock(); |
750 |
2848 |
try { |
751 |
2847 |
if (isAlreadyInserted(key, entry)) { |
752 |
205 |
return; |
753 |
|
} |
754 |
2642 |
addEntry(key, new SecurityCacheEntry(entry, wiki)); |
755 |
|
|
756 |
2640 |
logger.debug("Added access entry [{}] into the cache.", key); |
757 |
|
} finally { |
758 |
2848 |
newEntry = null; |
759 |
2848 |
writeLock.unlock(); |
760 |
|
} |
761 |
|
} |
762 |
|
|
763 |
|
|
764 |
|
|
765 |
|
@param |
766 |
|
@return |
767 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (4) |
Complexity: 2 |
Complexity Density: 1 |
|
768 |
1826 |
SecurityEntry get(String entryKey) {... |
769 |
1826 |
SecurityCacheEntry entry = cache.get(entryKey); |
770 |
1826 |
return (entry != null) ? entry.getEntry() : null; |
771 |
|
} |
772 |
|
|
|
|
| 71.4% |
Uncovered Elements: 4 (14) |
Complexity: 4 |
Complexity Density: 0.5 |
|
773 |
60415 |
@Override... |
774 |
|
public SecurityAccessEntry get(UserSecurityReference user, SecurityReference entity) |
775 |
|
{ |
776 |
60415 |
SecurityCacheEntry entry = getEntry(user, entity); |
777 |
60415 |
if (entry == null) { |
778 |
1145 |
if (logger.isDebugEnabled()) { |
779 |
0 |
logger.debug("Miss read access entry for [{}].", getEntryKey(user, entity)); |
780 |
|
} |
781 |
1145 |
return null; |
782 |
|
} |
783 |
59270 |
if (logger.isDebugEnabled()) { |
784 |
0 |
logger.debug("Success read access entry for [{}].", getEntryKey(user, entity)); |
785 |
|
} |
786 |
59270 |
return (SecurityAccessEntry) entry.getEntry(); |
787 |
|
} |
788 |
|
|
|
|
| 71.4% |
Uncovered Elements: 4 (14) |
Complexity: 4 |
Complexity Density: 0.5 |
|
789 |
82499 |
@Override... |
790 |
|
public SecurityRuleEntry get(SecurityReference entity) |
791 |
|
{ |
792 |
82498 |
SecurityCacheEntry entry = getEntry(entity); |
793 |
82499 |
if (entry == null) { |
794 |
3610 |
if (logger.isDebugEnabled()) { |
795 |
0 |
logger.debug("Miss read rule entry for [{}].", getEntryKey(entity)); |
796 |
|
} |
797 |
3610 |
return null; |
798 |
|
} |
799 |
78889 |
if (logger.isDebugEnabled()) { |
800 |
0 |
logger.debug("Success read rule entry for [{}].", getEntryKey(entity)); |
801 |
|
} |
802 |
78889 |
return (SecurityRuleEntry) entry.getEntry(); |
803 |
|
} |
804 |
|
|
|
|
| 75% |
Uncovered Elements: 3 (12) |
Complexity: 3 |
Complexity Density: 0.38 |
|
805 |
1 |
@Override... |
806 |
|
public void remove(UserSecurityReference user, SecurityReference entity) |
807 |
|
{ |
808 |
1 |
writeLock.lock(); |
809 |
1 |
try { |
810 |
1 |
SecurityCacheEntry entry = getEntry(user, entity); |
811 |
1 |
if (entry != null) { |
812 |
1 |
if (logger.isDebugEnabled()) { |
813 |
0 |
logger.debug("Remove outdated access entry for [{}].", getEntryKey(user, entity)); |
814 |
|
} |
815 |
1 |
this.cache.remove(entry.getKey()); |
816 |
|
} |
817 |
|
} finally { |
818 |
1 |
writeLock.unlock(); |
819 |
|
} |
820 |
|
} |
821 |
|
|
|
|
| 83.3% |
Uncovered Elements: 2 (12) |
Complexity: 3 |
Complexity Density: 0.38 |
|
822 |
4214 |
@Override... |
823 |
|
public void remove(SecurityReference entity) |
824 |
|
{ |
825 |
4214 |
writeLock.lock(); |
826 |
4214 |
try { |
827 |
4214 |
SecurityCacheEntry entry = getEntry(entity); |
828 |
4214 |
if (entry != null) { |
829 |
273 |
if (logger.isDebugEnabled()) { |
830 |
0 |
logger.debug("Remove outdated rule entry for [{}].", getEntryKey(entity)); |
831 |
|
} |
832 |
273 |
this.cache.remove(entry.getKey()); |
833 |
|
} |
834 |
|
} finally { |
835 |
4214 |
writeLock.unlock(); |
836 |
|
} |
837 |
|
} |
838 |
|
|
|
|
| 84.6% |
Uncovered Elements: 2 (13) |
Complexity: 4 |
Complexity Density: 0.44 |
|
839 |
15 |
@Override... |
840 |
|
public Collection<GroupSecurityReference> getImmediateGroupsFor(UserSecurityReference user) |
841 |
|
{ |
842 |
15 |
Collection<GroupSecurityReference> groups = new HashSet<>(); |
843 |
|
|
844 |
15 |
SecurityCacheEntry userEntry = getEntry(user); |
845 |
|
|
846 |
15 |
if (userEntry == null || !userEntry.isUser()) { |
847 |
|
|
848 |
0 |
return null; |
849 |
|
} |
850 |
|
|
851 |
15 |
for (SecurityCacheEntry parent : userEntry.parents) { |
852 |
|
|
853 |
16 |
SecurityReference parentRef = parent.getEntry().getReference(); |
854 |
16 |
if (parentRef instanceof GroupSecurityReference) { |
855 |
1 |
groups.add((GroupSecurityReference) parentRef); |
856 |
|
} |
857 |
|
} |
858 |
15 |
return groups; |
859 |
|
} |
860 |
|
|
|
|
| 96.9% |
Uncovered Elements: 1 (32) |
Complexity: 9 |
Complexity Density: 0.5 |
|
861 |
2524 |
@Override... |
862 |
|
public Collection<GroupSecurityReference> getGroupsFor(UserSecurityReference user, SecurityReference entityWiki) |
863 |
|
{ |
864 |
2524 |
Collection<GroupSecurityReference> groups = new HashSet<>(); |
865 |
|
|
866 |
2524 |
SecurityCacheEntry userEntry = (entityWiki != null) ? getShadowEntry(user, entityWiki) : getEntry(user); |
867 |
|
|
868 |
|
|
869 |
2524 |
if (userEntry == null || !userEntry.isUser()) { |
870 |
|
|
871 |
1297 |
return null; |
872 |
|
} |
873 |
|
|
874 |
|
|
875 |
|
|
876 |
1227 |
Deque<SecurityCacheEntry> entriesToExplore = new ArrayDeque<>(); |
877 |
|
|
878 |
|
|
879 |
1227 |
if (entityWiki != null) { |
880 |
|
|
881 |
31 |
addParentsWhenEntryIsShadow(userEntry, user, groups, entriesToExplore); |
882 |
|
} else { |
883 |
|
|
884 |
1196 |
entriesToExplore.add(userEntry); |
885 |
|
} |
886 |
|
|
887 |
|
|
888 |
3562 |
while (!entriesToExplore.isEmpty()) { |
889 |
2335 |
SecurityCacheEntry entry = entriesToExplore.pop(); |
890 |
|
|
891 |
|
|
892 |
2335 |
addParentsToTheListOfEntriesToExplore(entry.parents, groups, entriesToExplore); |
893 |
|
|
894 |
|
|
895 |
2335 |
if (entityWiki != null) { |
896 |
21 |
GroupSecurityReference entryRef = (GroupSecurityReference) entry.getEntry().getReference(); |
897 |
21 |
if (entryRef.isGlobal()) { |
898 |
8 |
SecurityCacheEntry shadow = getShadowEntry(entryRef, entityWiki); |
899 |
8 |
if (shadow != null) { |
900 |
8 |
addParentsToTheListOfEntriesToExplore(shadow.parents, groups, entriesToExplore, entry); |
901 |
|
} |
902 |
|
} |
903 |
|
} |
904 |
|
} |
905 |
|
|
906 |
1227 |
return groups; |
907 |
|
} |
908 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (3) |
Complexity: 1 |
Complexity Density: 0.33 |
|
909 |
31 |
private void addParentsWhenEntryIsShadow(SecurityCacheEntry shadow, UserSecurityReference user,... |
910 |
|
Collection<GroupSecurityReference> groups, |
911 |
|
Deque<SecurityCacheEntry> entriesToExplore) |
912 |
|
{ |
913 |
31 |
SecurityCacheEntry originalEntry = getEntry(user); |
914 |
|
|
915 |
|
|
916 |
31 |
addParentsToTheListOfEntriesToExplore(originalEntry.parents, groups, entriesToExplore); |
917 |
|
|
918 |
31 |
addParentsToTheListOfEntriesToExplore(shadow.parents, groups, entriesToExplore, originalEntry); |
919 |
|
} |
920 |
|
|
921 |
|
|
922 |
|
|
923 |
|
|
924 |
|
@param |
925 |
|
@param |
926 |
|
@param |
927 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
928 |
2366 |
private void addParentsToTheListOfEntriesToExplore(Collection<SecurityCacheEntry> parents,... |
929 |
|
Collection<GroupSecurityReference> groups, |
930 |
|
Deque<SecurityCacheEntry> entriesToExplore) |
931 |
|
{ |
932 |
2366 |
addParentsToTheListOfEntriesToExplore(parents, groups, entriesToExplore, null); |
933 |
|
} |
934 |
|
|
935 |
|
|
936 |
|
|
937 |
|
|
938 |
|
@param |
939 |
|
@param |
940 |
|
@param |
941 |
|
@param |
942 |
|
|
|
|
| 85.7% |
Uncovered Elements: 2 (14) |
Complexity: 6 |
Complexity Density: 0.75 |
|
943 |
2405 |
private void addParentsToTheListOfEntriesToExplore(Collection<SecurityCacheEntry> parents,... |
944 |
|
Collection<GroupSecurityReference> groups, |
945 |
|
Deque<SecurityCacheEntry> entriesToExplore, SecurityCacheEntry originalEntry) |
946 |
|
{ |
947 |
2405 |
if (parents == null) { |
948 |
0 |
return; |
949 |
|
} |
950 |
|
|
951 |
2405 |
for (SecurityCacheEntry parent : parents) { |
952 |
|
|
953 |
|
|
954 |
3552 |
if (originalEntry != null && parent == originalEntry) { |
955 |
39 |
continue; |
956 |
|
} |
957 |
|
|
958 |
|
|
959 |
3513 |
SecurityReference parentRef = parent.getEntry().getReference(); |
960 |
3513 |
if (parentRef instanceof GroupSecurityReference && groups.add((GroupSecurityReference) parentRef)) { |
961 |
1139 |
entriesToExplore.add(parent); |
962 |
|
} |
963 |
|
} |
964 |
|
} |
965 |
|
|
966 |
|
|
967 |
|
} |