|
33 | 33 | import java.util.List;
|
34 | 34 | import java.util.Map;
|
35 | 35 | import java.util.TreeMap;
|
| 36 | +import java.util.concurrent.locks.ReadWriteLock; |
| 37 | +import java.util.concurrent.locks.ReentrantReadWriteLock; |
36 | 38 | import java.util.function.Predicate;
|
37 | 39 | import java.util.jar.JarEntry;
|
38 | 40 | import java.util.jar.JarFile;
|
@@ -73,6 +75,11 @@ public final class AuthorizationFramework {
|
73 | 75 | */
|
74 | 76 | AuthorizationStack stack;
|
75 | 77 |
|
| 78 | + /** |
| 79 | + * Lock for safe reloads. |
| 80 | + */ |
| 81 | + private ReadWriteLock lock = new ReentrantReadWriteLock(); |
| 82 | + |
76 | 83 | /**
|
77 | 84 | * Keeping track of the number of reloads in this framework. This can be
|
78 | 85 | * used by the plugins to invalidate the session and force reload the
|
@@ -205,17 +212,27 @@ protected String getClassName(IAuthorizationPlugin plugin) {
|
205 | 212 | *
|
206 | 213 | * @return the stack containing plugins/other stacks
|
207 | 214 | */
|
208 |
| - public synchronized AuthorizationStack getStack() { |
209 |
| - return stack; |
| 215 | + public AuthorizationStack getStack() { |
| 216 | + lock.readLock().lock(); |
| 217 | + try { |
| 218 | + return stack; |
| 219 | + } finally { |
| 220 | + lock.readLock().unlock(); |
| 221 | + } |
210 | 222 | }
|
211 | 223 |
|
212 | 224 | /**
|
213 | 225 | * Set the internal stack to this new value.
|
214 | 226 | *
|
215 | 227 | * @param s new stack to be used
|
216 | 228 | */
|
217 |
| - public synchronized void setStack(AuthorizationStack s) { |
218 |
| - this.stack = s; |
| 229 | + public void setStack(AuthorizationStack s) { |
| 230 | + lock.writeLock().lock(); |
| 231 | + try { |
| 232 | + this.stack = s; |
| 233 | + } finally { |
| 234 | + lock.writeLock().unlock(); |
| 235 | + } |
219 | 236 | }
|
220 | 237 |
|
221 | 238 | /**
|
@@ -495,16 +512,20 @@ public Object run() {
|
495 | 512 | // fire load events
|
496 | 513 | loadAllPlugins(newStack);
|
497 | 514 |
|
| 515 | + AuthorizationStack oldStack; |
498 | 516 | /**
|
499 |
| - * Replace the stack in a synchronized block to avoid inconsistent state |
500 |
| - * between the stack change and currently executing requests performing |
501 |
| - * some authorization on the same stack. |
| 517 | + * Replace the stack in a write lock to avoid inconsistent state between |
| 518 | + * the stack change and currently executing requests performing some |
| 519 | + * authorization on the same stack. |
502 | 520 | *
|
503 |
| - * @see #performCheck is also marked as synchronized |
| 521 | + * @see #performCheck is controlled with a read lock |
504 | 522 | */
|
505 |
| - AuthorizationStack oldStack = stack; |
506 |
| - synchronized (this) { |
| 523 | + lock.writeLock().lock(); |
| 524 | + try { |
| 525 | + oldStack = stack; |
507 | 526 | stack = newStack;
|
| 527 | + } finally { |
| 528 | + lock.writeLock().unlock(); |
508 | 529 | }
|
509 | 530 |
|
510 | 531 | // clean the old stack
|
@@ -546,7 +567,8 @@ public void setPluginVersion(int pluginVersion) {
|
546 | 567 | }
|
547 | 568 |
|
548 | 569 | /**
|
549 |
| - * Checks if the request should have an access to a resource. |
| 570 | + * Checks if the request should have an access to a resource. This method is |
| 571 | + * thread safe with respect to the concurrent reload of plugins. |
550 | 572 | *
|
551 | 573 | * <p>
|
552 | 574 | * Internally performed with a predicate. Using cache in request
|
@@ -645,7 +667,12 @@ private boolean checkAll(HttpServletRequest request, String cache, Nameable enti
|
645 | 667 | * successful for the given plugin
|
646 | 668 | * @return true if entity is allowed; false otherwise
|
647 | 669 | */
|
648 |
| - private synchronized boolean performCheck(Nameable entity, Predicate<IAuthorizationPlugin> predicate) { |
649 |
| - return stack.isAllowed(entity, predicate); |
| 670 | + private boolean performCheck(Nameable entity, Predicate<IAuthorizationPlugin> predicate) { |
| 671 | + lock.readLock().lock(); |
| 672 | + try { |
| 673 | + return stack.isAllowed(entity, predicate); |
| 674 | + } finally { |
| 675 | + lock.readLock().unlock(); |
| 676 | + } |
650 | 677 | }
|
651 | 678 | }
|
0 commit comments