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 // }