Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
SubjectRunnable |
|
| 2.0;2 |
1 | /* | |
2 | * Licensed to the Apache Software Foundation (ASF) under one | |
3 | * or more contributor license agreements. See the NOTICE file | |
4 | * distributed with this work for additional information | |
5 | * regarding copyright ownership. The ASF licenses this file | |
6 | * to you under the Apache License, Version 2.0 (the | |
7 | * "License"); you may not use this file except in compliance | |
8 | * with the License. You may obtain a copy of the License at | |
9 | * | |
10 | * http://www.apache.org/licenses/LICENSE-2.0 | |
11 | * | |
12 | * Unless required by applicable law or agreed to in writing, | |
13 | * software distributed under the License is distributed on an | |
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
15 | * KIND, either express or implied. See the License for the | |
16 | * specific language governing permissions and limitations | |
17 | * under the License. | |
18 | */ | |
19 | package org.apache.shiro.subject.support; | |
20 | ||
21 | import org.apache.shiro.subject.Subject; | |
22 | import org.apache.shiro.util.ThreadState; | |
23 | ||
24 | /** | |
25 | * A {@code SubjectRunnable} ensures that a target/delegate {@link Runnable Runnable} will execute such that any | |
26 | * call to {@code SecurityUtils.}{@link org.apache.shiro.SecurityUtils#getSubject() getSubject()} during the | |
27 | * {@code Runnable}'s execution will return the associated {@code Subject} instance. The {@code SubjectRunnable} | |
28 | * instance can be run on any thread (the current thread or asynchronously on another thread) and the | |
29 | * {@code SecurityUtils.getSubject()} call will still work properly. This implementation also guarantees that Shiro's | |
30 | * thread state will be identical before and after execution to ensure threads remain clean in any thread-pooled | |
31 | * environment. | |
32 | * <p/> | |
33 | * When instances of this class {@link Runnable#run() run()}, the following occurs: | |
34 | * <ol> | |
35 | * <li>The Subject and any of its associated thread state is first bound to the thread that executes the | |
36 | * {@code Runnable}.</li> | |
37 | * <li>The delegate/target {@code Runnable} is {@link #doRun(Runnable) run}</li> | |
38 | * <li>Any previous thread state that might have existed before the {@code Subject} was bound is fully restored</li> | |
39 | * </ol> | |
40 | * <p/> | |
41 | * | |
42 | * <h3>Usage</h3> | |
43 | * | |
44 | * This is typically considered a support class and is not often directly referenced. Most people prefer to use | |
45 | * the {@code Subject.}{@link Subject#execute(Runnable) execute} or | |
46 | * {@code Subject.}{@link Subject#associateWith(Runnable) associateWith} methods, which transparently perform the | |
47 | * necessary association logic. | |
48 | * <p/> | |
49 | * An even more convenient alternative is to use a | |
50 | * {@link org.apache.shiro.concurrent.SubjectAwareExecutor SubjectAwareExecutor}, which transparently uses | |
51 | * instances of this class but does not require referencing Shiro's API at all. | |
52 | * | |
53 | * @see Subject#associateWith(Runnable) | |
54 | * @see org.apache.shiro.concurrent.SubjectAwareExecutor SubjectAwareExecutor | |
55 | * @since 1.0 | |
56 | */ | |
57 | public class SubjectRunnable implements Runnable { | |
58 | ||
59 | protected final ThreadState threadState; | |
60 | private final Runnable runnable; | |
61 | ||
62 | /** | |
63 | * Creates a new {@code SubjectRunnable} that, when executed, will execute the target {@code delegate}, but | |
64 | * guarantees that it will run associated with the specified {@code Subject}. | |
65 | * | |
66 | * @param subject the Subject to associate with the delegate's execution. | |
67 | * @param delegate the runnable to run. | |
68 | */ | |
69 | public SubjectRunnable(Subject subject, Runnable delegate) { | |
70 | 4 | this(new SubjectThreadState(subject), delegate); |
71 | 4 | } |
72 | ||
73 | /** | |
74 | * Creates a new {@code SubjectRunnable} that, when executed, will perform thread state | |
75 | * {@link ThreadState#bind binding} and guaranteed {@link ThreadState#restore restoration} before and after the | |
76 | * {@link Runnable Runnable}'s execution, respectively. | |
77 | * | |
78 | * @param threadState the thread state to bind and unbind before and after the runnable's execution. | |
79 | * @param delegate the delegate {@code Runnable} to execute when this instance is {@link #run() run()}. | |
80 | * @throws IllegalArgumentException if either the {@code ThreadState} or {@link Runnable} arguments are {@code null}. | |
81 | */ | |
82 | 4 | protected SubjectRunnable(ThreadState threadState, Runnable delegate) throws IllegalArgumentException { |
83 | 4 | if (threadState == null) { |
84 | 0 | throw new IllegalArgumentException("ThreadState argument cannot be null."); |
85 | } | |
86 | 4 | this.threadState = threadState; |
87 | 4 | if (delegate == null) { |
88 | 0 | throw new IllegalArgumentException("Runnable argument cannot be null."); |
89 | } | |
90 | 4 | this.runnable = delegate; |
91 | 4 | } |
92 | ||
93 | /** | |
94 | * {@link ThreadState#bind Bind}s the Subject thread state, executes the target {@code Runnable} and then guarantees | |
95 | * the previous thread state's {@link ThreadState#restore restoration}: | |
96 | * <pre> | |
97 | * try { | |
98 | * threadState.{@link ThreadState#bind bind()}; | |
99 | * {@link #doRun doRun}(targetRunnable); | |
100 | * } finally { | |
101 | * threadState.{@link ThreadState#restore restore()} | |
102 | * } | |
103 | * </pre> | |
104 | */ | |
105 | public void run() { | |
106 | try { | |
107 | 2 | threadState.bind(); |
108 | 2 | doRun(this.runnable); |
109 | } finally { | |
110 | 2 | threadState.restore(); |
111 | 2 | } |
112 | 2 | } |
113 | ||
114 | /** | |
115 | * Simply calls the target {@link Runnable Runnable}'s {@link Runnable#run run()} method. | |
116 | * | |
117 | * @param runnable the target runnable to run. | |
118 | */ | |
119 | protected void doRun(Runnable runnable) { | |
120 | 2 | runnable.run(); |
121 | 2 | } |
122 | } |