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 module hunt.shiro.concurrent.SubjectAwareExecutorService;
20 
21 import hunt.shiro.subject.Subject;
22 
23 import hunt.collection;
24 
25 /**
26  * {@code ExecutorService} implementation that will automatically first associate any argument
27  * {@link Runnable} or {@link Callable} instances with the {@link #getSubject currently available subject} and then
28  * dispatch the Subject-enabled runnable or callable to an underlying delegate
29  * {@link java.util.concurrent.ExecutorService ExecutorService} instance.  The principle is the same as the
30  * parent {@link SubjectAwareExecutor} class, but enables the richer {@link ExecutorService} API.
31  * <p/>
32  * This is a simplification for applications that want to execute code as the currently
33  * executing {@code Subject} on another thread, but don't want or need to call the
34  * {@link Subject#associateWith(Runnable)} or {@link Subject#associateWith(Callable)} methods and dispatch them to a
35  * Thread manually.  This simplifies code and reduces Shiro dependencies across application source code.
36  * <p/>
37  * Consider this code that could be repeated in many places across an application:
38  * <pre>
39  * {@link Callable Callable} applicationWork = //instantiate or acquire Callable from somewhere
40  * {@link Subject Subject} subject = {@link hunt.shiro.SecurityUtils SecurityUtils}.{@link hunt.shiro.SecurityUtils#getSubject() getSubject()};
41  * {@link Callable Callable} work = subject.{@link Subject#associateWith(Callable) associateWith(applicationWork)};
42  * {@link ExecutorService anExecutorService}.{@link ExecutorService#submit(Callable) submit(work)};
43  * </pre>
44  * Instead, if the {@code ExecutorService} instance used at runtime is an instance of this class
45  * (which delegates to the target ExecutorService that you want), all places in code like the above reduce to this:
46  * <pre>
47  * {@link Callable Callable} applicationWork = //instantiate or acquire Callable from somewhere
48  * {@link ExecutorService anExecutorService}.{@link ExecutorService#submit(Callable) submit(work)};
49  * </pre>
50  * Notice there is no use of the Shiro API in the 2nd code block, encouraging the principle of loose coupling across
51  * your codebase.
52  *
53  */
54 // class SubjectAwareExecutorService : SubjectAwareExecutor, ExecutorService {
55 
56 //     private ExecutorService targetExecutorService;
57 
58 //      this() {
59 //     }
60 
61 //      this(ExecutorService target) {
62 //         setTargetExecutorService(target);
63 //     }
64 
65 //      ExecutorService getTargetExecutorService() {
66 //         return targetExecutorService;
67 //     }
68 
69 //      void setTargetExecutorService(ExecutorService targetExecutorService) {
70 //         super.setTargetExecutor(targetExecutorService);
71 //         this.targetExecutorService = targetExecutorService;
72 //     }
73 
74 //     override
75 //      void setTargetExecutor(Executor targetExecutor) {
76 //         auto targetExecutorCast = cast(ExecutorService)targetExecutor;
77 //         if (targetExecutorCast is null) {
78 //             string msg = "The SubjectAwareExecutorService implementation only accepts " ~
79 //                          "ExecutorService target instances.";
80 //             throw new IllegalArgumentException(msg);
81 //         }
82 //         super.setTargetExecutor(targetExecutor);
83 //     }
84 
85 //      void shutdown() {
86 //         this.targetExecutorService.shutdown();
87 //     }
88 
89 //      List!(Runnable) shutdownNow() {
90 //         return this.targetExecutorService.shutdownNow();
91 //     }
92 
93 //      bool isShutdown() {
94 //         return this.targetExecutorService.isShutdown();
95 //     }
96 
97 //      bool isTerminated() {
98 //         return this.targetExecutorService.isTerminated();
99 //     }
100 
101 //      bool awaitTermination(long timeout, TimeUnit unit){
102 //         return this.targetExecutorService.awaitTermination(timeout, unit);
103 //     }
104 
105 //     protected <T> Callable!(T) associateWithSubject(Callable!(T) task) {
106 //         Subject subject = getSubject();
107 //         return subject.associateWith(task);
108 //     }
109 
110 //      <T> Future!(T) submit(Callable!(T) task) {
111 //         Callable!(T) work = associateWithSubject(task);
112 //         return this.targetExecutorService.submit(work);
113 //     }
114 
115 //      <T> Future!(T) submit(Runnable task, T result) {
116 //         Runnable work = associateWithSubject(task);
117 //         return this.targetExecutorService.submit(work, result);
118 //     }
119 
120 //      Future<?> submit(Runnable task) {
121 //         Runnable work = associateWithSubject(task);
122 //         return this.targetExecutorService.submit(work);
123 //     }
124 
125 //     protected <T> Collection!(Callable!(T)) associateWithSubject(Collection<? extends Callable!(T)> tasks) {
126 //         Collection!(Callable!(T)) workItems = new ArrayList!(Callable!(T))(tasks.size());
127 //         for (Callable!(T) task : tasks) {
128 //             Callable!(T) work = associateWithSubject(task);
129 //             workItems.add(work);
130 //         }
131 //         return workItems;
132 //     }
133 
134 //      <T> List!(Future!(T)) invokeAll(Collection<? extends Callable!(T)> tasks){
135 //         Collection!(Callable!(T)) workItems = associateWithSubject(tasks);
136 //         return this.targetExecutorService.invokeAll(workItems);
137 //     }
138 
139 //      <T> List!(Future!(T)) invokeAll(Collection<? extends Callable!(T)> tasks, long timeout, TimeUnit unit){
140 //         Collection!(Callable!(T)) workItems = associateWithSubject(tasks);
141 //         return this.targetExecutorService.invokeAll(workItems, timeout, unit);
142 //     }
143 
144 //      <T> T invokeAny(Collection<? extends Callable!(T)> tasks){
145 //         Collection!(Callable!(T)) workItems = associateWithSubject(tasks);
146 //         return this.targetExecutorService.invokeAny(workItems);
147 //     }
148 
149 //      <T> T invokeAny(Collection<? extends Callable!(T)> tasks, long timeout, TimeUnit unit){
150 //         Collection!(Callable!(T)) workItems = associateWithSubject(tasks);
151 //         return this.targetExecutorService.invokeAny(workItems, timeout, unit);
152 //     }
153 // }