![JAR search and dependency download from the Maven repository](/logo.png)
org.echocat.jomon.spring.ContextLoadThreadGroup Maven / Gradle / Ivy
/*****************************************************************************************
* *** BEGIN LICENSE BLOCK *****
*
* Version: MPL 2.0
*
* echocat Jomon, Copyright (c) 2012-2014 echocat
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* *** END LICENSE BLOCK *****
****************************************************************************************/
package org.echocat.jomon.spring;
import org.echocat.jomon.runtime.concurrent.StopWatch;
import org.echocat.jomon.runtime.util.Duration;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.*;
import static java.util.Collections.synchronizedMap;
import static java.util.Collections.synchronizedSet;
import static java.util.Collections.unmodifiableSet;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
public class ContextLoadThreadGroup implements ApplicationContextAware, Iterable, UncaughtExceptionHandler {
private final Map> _failedThreads = synchronizedMap(new HashMap>());
private final Set _threads = synchronizedSet(new HashSet());
private String _name;
public void addAndStart(@Nonnull Thread thread) {
thread.setUncaughtExceptionHandler(this);
_threads.add(thread);
thread.start();
}
public void join() throws InterruptedException {
for (final Thread thread : this) {
if (thread.isAlive()) {
thread.join();
}
}
throwRuntimeExceptionOn();
}
public boolean join(@Nonnull Duration duration) throws InterruptedException {
boolean result = true;
final Iterator i = iterator();
final StopWatch stopWatch = new StopWatch();
while (result && i.hasNext()) {
final Thread thread = i.next();
if (thread.isAlive()) {
thread.join(duration.minus(stopWatch.getCurrentDuration()).in(MILLISECONDS));
}
result = !thread.isAlive();
}
if (result) {
throwRuntimeExceptionOn();
}
return result;
}
public void throwExceptionOn() throws Exception {
throwOn(Exception.class);
}
public void throwRuntimeExceptionOn() throws RuntimeException {
throwOn(RuntimeException.class);
}
public void throwOn(@Nonnull Class allowedThrowableType) throws T {
synchronized (_failedThreads) {
final Throwable highestRatedThrowable = findHighestRatedThrowableIn(_failedThreads);
if (highestRatedThrowable != null) {
for (final List throwables : _failedThreads.values()) {
for (final Throwable throwable : throwables) {
if (!highestRatedThrowable.equals(throwable)) {
highestRatedThrowable.addSuppressed(throwable);
}
}
}
if (allowedThrowableType.isInstance(highestRatedThrowable)) {
throw allowedThrowableType.cast(highestRatedThrowable);
} else if (highestRatedThrowable instanceof RuntimeException) {
throw (RuntimeException) highestRatedThrowable;
} else if (highestRatedThrowable instanceof Error) {
throw (Error) highestRatedThrowable;
} else {
throw new RuntimeException(highestRatedThrowable);
}
}
}
}
@Nullable
protected Throwable findHighestRatedThrowableIn(@Nonnull Map> threadToExceptions) {
Throwable result = null;
for (final List exceptions : threadToExceptions.values()) {
final Throwable current = findHighestRatedThrowableIn(exceptions);
if (isHigherRated(current, result)) {
result = current;
}
}
return result;
}
@Nullable
protected Throwable findHighestRatedThrowableIn(@Nonnull Iterable exceptions) {
Throwable result = null;
for (final Throwable exception : exceptions) {
if (isHigherRated(exception, result)) {
result = exception;
}
}
return result;
}
protected boolean isHigherRated(@Nonnull Throwable what, @Nullable Throwable inRelationTo) {
final boolean result;
if (inRelationTo instanceof Error) {
result = false;
} else if (inRelationTo instanceof Throwable && !(inRelationTo instanceof Exception)) {
result = what instanceof Error;
} else if (inRelationTo != null) {
result = what instanceof Error || (what instanceof Throwable && !(what instanceof Exception));
} else {
result = true;
}
return result;
}
public boolean isAtLeastOneThreadAlive() {
boolean result = false;
final Iterator i = iterator();
while (!result && i.hasNext()) {
result = i.next().isAlive();
}
return result;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if (_name == null) {
_name = applicationContext.getDisplayName();
}
}
@Override
public Iterator iterator() {
return getThreads().iterator();
}
@Nonnull
public Set getThreads() {
final Set threads;
synchronized (_threads) {
threads = unmodifiableSet(new HashSet<>(_threads));
}
return threads;
}
public String getName() {
return _name;
}
public void setName(String name) {
_name = name;
}
@Nonnull
protected String getNameInternal() {
final String name = _name;
return name != null ? name : "ContextLoadThreadGroup";
}
@Override
public void uncaughtException(Thread t, Throwable e) {
synchronized (_failedThreads) {
List throwables = _failedThreads.get(t);
if (throwables == null) {
throwables = new ArrayList<>();
_failedThreads.put(t, throwables);
}
throwables.add(e);
}
}
@Override
public String toString() {
return getNameInternal();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy