org.apache.shiro.concurrent.SubjectAwareExecutorService Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.shiro.concurrent;
import org.apache.shiro.subject.Subject;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.*;
/**
* {@code ExecutorService} implementation that will automatically first associate any argument
* {@link Runnable} or {@link Callable} instances with the {@link #getSubject currently available subject} and then
* dispatch the Subject-enabled runnable or callable to an underlying delegate
* {@link java.util.concurrent.ExecutorService ExecutorService} instance. The principle is the same as the
* parent {@link SubjectAwareExecutor} class, but enables the richer {@link ExecutorService} API.
*
* This is a simplification for applications that want to execute code as the currently
* executing {@code Subject} on another thread, but don't want or need to call the
* {@link Subject#associateWith(Runnable)} or {@link Subject#associateWith(Callable)} methods and dispatch them to a
* Thread manually. This simplifies code and reduces Shiro dependencies across application source code.
*
* Consider this code that could be repeated in many places across an application:
*
* {@link Callable Callable} applicationWork = //instantiate or acquire Callable from somewhere
* {@link Subject Subject} subject = {@link org.apache.shiro.SecurityUtils SecurityUtils}.{@link org.apache.shiro.SecurityUtils#getSubject() getSubject()};
* {@link Callable Callable} work = subject.{@link Subject#associateWith(Callable) associateWith(applicationWork)};
* {@link ExecutorService anExecutorService}.{@link ExecutorService#submit(Callable) submit(work)};
*
* Instead, if the {@code ExecutorService} instance used at runtime is an instance of this class
* (which delegates to the target ExecutorService that you want), all places in code like the above reduce to this:
*
* {@link Callable Callable} applicationWork = //instantiate or acquire Callable from somewhere
* {@link ExecutorService anExecutorService}.{@link ExecutorService#submit(Callable) submit(work)};
*
* Notice there is no use of the Shiro API in the 2nd code block, encouraging the principle of loose coupling across
* your codebase.
*
* @since 1.0
*/
public class SubjectAwareExecutorService extends SubjectAwareExecutor implements ExecutorService {
private ExecutorService targetExecutorService;
public SubjectAwareExecutorService() {
}
public SubjectAwareExecutorService(ExecutorService target) {
setTargetExecutorService(target);
}
public ExecutorService getTargetExecutorService() {
return targetExecutorService;
}
public void setTargetExecutorService(ExecutorService targetExecutorService) {
super.setTargetExecutor(targetExecutorService);
this.targetExecutorService = targetExecutorService;
}
@Override
public void setTargetExecutor(Executor targetExecutor) {
if (!(targetExecutor instanceof ExecutorService)) {
String msg = "The " + getClass().getName() + " implementation only accepts " +
ExecutorService.class.getName() + " target instances.";
throw new IllegalArgumentException(msg);
}
super.setTargetExecutor(targetExecutor);
}
public void shutdown() {
this.targetExecutorService.shutdown();
}
public List shutdownNow() {
return this.targetExecutorService.shutdownNow();
}
public boolean isShutdown() {
return this.targetExecutorService.isShutdown();
}
public boolean isTerminated() {
return this.targetExecutorService.isTerminated();
}
public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
return this.targetExecutorService.awaitTermination(timeout, unit);
}
protected Callable associateWithSubject(Callable task) {
Subject subject = getSubject();
return subject.associateWith(task);
}
public Future submit(Callable task) {
Callable work = associateWithSubject(task);
return this.targetExecutorService.submit(work);
}
public Future submit(Runnable task, T result) {
Runnable work = associateWithSubject(task);
return this.targetExecutorService.submit(work, result);
}
public Future> submit(Runnable task) {
Runnable work = associateWithSubject(task);
return this.targetExecutorService.submit(work);
}
protected Collection> associateWithSubject(Collection extends Callable> tasks) {
Collection> workItems = new ArrayList>(tasks.size());
for (Callable task : tasks) {
Callable work = associateWithSubject(task);
workItems.add(work);
}
return workItems;
}
public List> invokeAll(Collection extends Callable> tasks) throws InterruptedException {
Collection> workItems = associateWithSubject(tasks);
return this.targetExecutorService.invokeAll(workItems);
}
public List> invokeAll(Collection extends Callable> tasks, long timeout, TimeUnit unit)
throws InterruptedException {
Collection> workItems = associateWithSubject(tasks);
return this.targetExecutorService.invokeAll(workItems, timeout, unit);
}
public T invokeAny(Collection extends Callable> tasks) throws InterruptedException, ExecutionException {
Collection> workItems = associateWithSubject(tasks);
return this.targetExecutorService.invokeAny(workItems);
}
public T invokeAny(Collection extends Callable> tasks, long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException {
Collection> workItems = associateWithSubject(tasks);
return this.targetExecutorService.invokeAny(workItems, timeout, unit);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy