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    }