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 */ 019package org.apache.shiro.concurrent; 020 021import org.apache.shiro.SecurityUtils; 022import org.apache.shiro.subject.Subject; 023 024import 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 */ 056public 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}