001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied. See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019 package org.apache.shiro.concurrent;
020
021 import org.apache.shiro.SecurityUtils;
022 import org.apache.shiro.subject.Subject;
023
024 import java.util.concurrent.Executor;
025
026 /**
027 * {@code Executor} implementation that will automatically first associate any argument
028 * {@link Runnable} instances with the currently available {@link Subject} and then
029 * dispatch the Subject-enabled runnable to an underlying delegate {@link Executor}
030 * instance.
031 * <p/>
032 * This is a simplification for applications that want to execute code as the currently
033 * executing {@code Subject} on another thread, but don't want or need to call the
034 * {@link Subject#associateWith(Runnable)} method and dispatch to a Thread manually. This
035 * simplifies code and reduces Shiro dependencies across application source code.
036 * <p/>
037 * Consider this code that could be repeated in many places across an application:
038 * <pre>
039 * {@link Runnable Runnable} applicationWork = //instantiate or acquire Runnable from somewhere
040 * {@link Subject Subject} subject = {@link SecurityUtils SecurityUtils}.{@link SecurityUtils#getSubject() getSubject()};
041 * {@link Runnable Runnable} work = subject.{@link Subject#associateWith(Runnable) associateWith(applicationWork)};
042 * {@link Executor anExecutor}.{@link Executor#execute(Runnable) execute(work)};
043 * </pre>
044 * Instead, if the {@code Executor} instance used in application code is an instance of this class (which delegates
045 * to the target Executor that you want), all places in code like the above reduce to this:
046 * <pre>
047 * {@link Runnable Runnable} applicationWork = //instantiate or acquire Runnable from somewhere
048 * {@link Executor anExecutor}.{@link Executor#execute(Runnable) execute(work)};
049 * </pre>
050 * Notice there is no use of the Shiro API in the 2nd code block, encouraging the principle of loose coupling across
051 * your codebase.
052 *
053 * @see SubjectAwareExecutorService
054 * @since 1.0
055 */
056 public class SubjectAwareExecutor implements Executor {
057
058 /**
059 * The target Executor instance that will actually execute the subject-associated Runnable instances.
060 */
061 private Executor targetExecutor;
062
063 public SubjectAwareExecutor() {
064 }
065
066 public SubjectAwareExecutor(Executor targetExecutor) {
067 if (targetExecutor == null) {
068 throw new NullPointerException("target Executor instance cannot be null.");
069 }
070 this.targetExecutor = targetExecutor;
071 }
072
073 /**
074 * Returns the target Executor instance that will actually execute the subject-associated Runnable instances.
075 *
076 * @return target Executor instance that will actually execute the subject-associated Runnable instances.
077 */
078 public Executor getTargetExecutor() {
079 return targetExecutor;
080 }
081
082 /**
083 * Sets target Executor instance that will actually execute the subject-associated Runnable instances.
084 *
085 * @param targetExecutor the target Executor instance that will actually execute the subject-associated Runnable
086 * instances.
087 */
088 public void setTargetExecutor(Executor targetExecutor) {
089 this.targetExecutor = targetExecutor;
090 }
091
092 /**
093 * Returns the currently Subject instance that should be associated with Runnable or Callable instances before
094 * being dispatched to the target {@code Executor} instance. This implementation merely defaults to returning
095 * {@code SecurityUtils}.{@link SecurityUtils#getSubject() getSubject()}.
096 *
097 * @return the currently Subject instance that should be associated with Runnable or Callable instances before
098 * being dispatched to the target {@code Executor} instance.
099 */
100 protected Subject getSubject() {
101 return SecurityUtils.getSubject();
102 }
103
104 /**
105 * Utility method for subclasses to associate the argument {@code Runnable} with the currently executing subject
106 * and then return the associated Runnable. The default implementation merely defaults to
107 * <pre>
108 * Subject subject = {@link #getSubject() getSubject()};
109 * return subject.{@link Subject#associateWith(Runnable) associateWith(r)};
110 * </pre>
111 *
112 * @param r the argument runnable to be associated with the current subject
113 * @return the associated runnable instance reflecting the current subject
114 */
115 protected Runnable associateWithSubject(Runnable r) {
116 Subject subject = getSubject();
117 return subject.associateWith(r);
118 }
119
120 /**
121 * Executes the specified runnable by first associating it with the currently executing {@code Subject} and then
122 * dispatches the associated Runnable to the underlying target {@link Executor} instance.
123 *
124 * @param command the runnable to associate with the currently executing subject and then to execute via the target
125 * {@code Executor} instance.
126 */
127 public void execute(Runnable command) {
128 Runnable associated = associateWithSubject(command);
129 getTargetExecutor().execute(associated);
130 }
131 }