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.SubjectAwareExecutor; 20 21 import hunt.shiro.SecurityUtils; 22 import hunt.shiro.subject.Subject; 23 24 import hunt.Exceptions; 25 import hunt.util.Common; 26 import hunt.util.Runnable; 27 28 29 /** 30 * {@code Executor} implementation that will automatically first associate any argument 31 * {@link Runnable} instances with the currently available {@link Subject} and then 32 * dispatch the Subject-enabled runnable to an underlying delegate {@link Executor} 33 * instance. 34 * <p/> 35 * This is a simplification for applications that want to execute code as the currently 36 * executing {@code Subject} on another thread, but don't want or need to call the 37 * {@link Subject#associateWith(Runnable)} method and dispatch to a Thread manually. This 38 * simplifies code and reduces Shiro dependencies across application source code. 39 * <p/> 40 * Consider this code that could be repeated in many places across an application: 41 * <pre> 42 * {@link Runnable Runnable} applicationWork = //instantiate or acquire Runnable from somewhere 43 * {@link Subject Subject} subject = {@link SecurityUtils SecurityUtils}.{@link SecurityUtils#getSubject() getSubject()}; 44 * {@link Runnable Runnable} work = subject.{@link Subject#associateWith(Runnable) associateWith(applicationWork)}; 45 * {@link Executor anExecutor}.{@link Executor#execute(Runnable) execute(work)}; 46 * </pre> 47 * Instead, if the {@code Executor} instance used in application code is an instance of this class (which delegates 48 * to the target Executor that you want), all places in code like the above reduce to this: 49 * <pre> 50 * {@link Runnable Runnable} applicationWork = //instantiate or acquire Runnable from somewhere 51 * {@link Executor anExecutor}.{@link Executor#execute(Runnable) execute(work)}; 52 * </pre> 53 * Notice there is no use of the Shiro API in the 2nd code block, encouraging the principle of loose coupling across 54 * your codebase. 55 * 56 * @see SubjectAwareExecutorService 57 */ 58 class SubjectAwareExecutor : Executor { 59 60 /** 61 * The target Executor instance that will actually execute the subject-associated Runnable instances. 62 */ 63 private Executor targetExecutor; 64 65 this() { 66 } 67 68 this(Executor targetExecutor) { 69 if (targetExecutor is null) { 70 throw new NullPointerException("target Executor instance cannot be null."); 71 } 72 this.targetExecutor = targetExecutor; 73 } 74 75 /** 76 * Returns the target Executor instance that will actually execute the subject-associated Runnable instances. 77 * 78 * @return target Executor instance that will actually execute the subject-associated Runnable instances. 79 */ 80 Executor getTargetExecutor() { 81 return targetExecutor; 82 } 83 84 /** 85 * Sets target Executor instance that will actually execute the subject-associated Runnable instances. 86 * 87 * @param targetExecutor the target Executor instance that will actually execute the subject-associated Runnable 88 * instances. 89 */ 90 void setTargetExecutor(Executor targetExecutor) { 91 this.targetExecutor = targetExecutor; 92 } 93 94 /** 95 * Returns the currently Subject instance that should be associated with Runnable or Callable instances before 96 * being dispatched to the target {@code Executor} instance. This implementation merely defaults to returning 97 * {@code SecurityUtils}.{@link SecurityUtils#getSubject() getSubject()}. 98 * 99 * @return the currently Subject instance that should be associated with Runnable or Callable instances before 100 * being dispatched to the target {@code Executor} instance. 101 */ 102 // protected Subject getSubject() { 103 // return SecurityUtils.getSubject(); 104 // } 105 106 /** 107 * Utility method for subclasses to associate the argument {@code Runnable} with the currently executing subject 108 * and then return the associated Runnable. The default implementation merely defaults to 109 * <pre> 110 * Subject subject = {@link #getSubject() getSubject()}; 111 * return subject.{@link Subject#associateWith(Runnable) associateWith(r)}; 112 * </pre> 113 * 114 * @param r the argument runnable to be associated with the current subject 115 * @return the associated runnable instance reflecting the current subject 116 */ 117 // protected Runnable associateWithSubject(Runnable r) { 118 // Subject subject = getSubject(); 119 // return subject.associateWith(r); 120 // } 121 122 /** 123 * Executes the specified runnable by first associating it with the currently executing {@code Subject} and then 124 * dispatches the associated Runnable to the underlying target {@link Executor} instance. 125 * 126 * @param command the runnable to associate with the currently executing subject and then to execute via the target 127 * {@code Executor} instance. 128 */ 129 void execute(Runnable command) { 130 import hunt.logging.Logger; 131 warning("dddddddddddddddddddddd"); 132 // Runnable associated = associateWithSubject(command); 133 // getTargetExecutor().execute(associated); 134 } 135 }