| 1 | /******************************************************************************* | |
| 2 | * Copyhacked (H) 2012-2025. | |
| 3 | * This program and the accompanying materials | |
| 4 | * are made available under no term at all, use it like | |
| 5 | * you want, but share and discuss it | |
| 6 | * every time possible with every body. | |
| 7 | * | |
| 8 | * Contributors: | |
| 9 | * ron190 at ymail dot com - initial implementation | |
| 10 | ******************************************************************************/ | |
| 11 | package com.jsql.util; | |
| 12 | ||
| 13 | import com.jsql.model.InjectionModel; | |
| 14 | import com.jsql.model.bean.database.AbstractElementDatabase; | |
| 15 | import com.jsql.model.suspendable.AbstractSuspendable; | |
| 16 | import com.jsql.model.suspendable.callable.ThreadFactoryCallable; | |
| 17 | import org.apache.logging.log4j.LogManager; | |
| 18 | import org.apache.logging.log4j.Logger; | |
| 19 | ||
| 20 | import java.util.HashMap; | |
| 21 | import java.util.Map; | |
| 22 | import java.util.concurrent.ConcurrentHashMap; | |
| 23 | import java.util.concurrent.ExecutorService; | |
| 24 | import java.util.concurrent.Executors; | |
| 25 | import java.util.concurrent.TimeUnit; | |
| 26 | ||
| 27 | /** | |
| 28 | * Utility class managing running threads on which the user can act. | |
| 29 | * It must be noted that as SwingWorker class are used then only 10 jobs can be run | |
| 30 | * at the same time, the 11th will be waiting in the thread pool until one of the 10 | |
| 31 | * actives one is freed. | |
| 32 | */ | |
| 33 | public final class ThreadUtil { | |
| 34 | | |
| 35 | private static final Logger LOGGER = LogManager.getRootLogger(); | |
| 36 | | |
| 37 | /** | |
| 38 | * List of running jobs associated to a database injection task. | |
| 39 | * We can interact with those tasks in order to pause/resume and stop the process. | |
| 40 | */ | |
| 41 | // Fix #8258: ConcurrentModificationException on java.util.HashMap$ValueIterator.next() | |
| 42 | private final Map<AbstractElementDatabase, AbstractSuspendable> suspendables = new ConcurrentHashMap<>(new HashMap<>()); | |
| 43 | ||
| 44 | private final InjectionModel injectionModel; | |
| 45 | | |
| 46 | public ThreadUtil(InjectionModel injectionModel) { | |
| 47 | this.injectionModel = injectionModel; | |
| 48 | } | |
| 49 | ||
| 50 | /** | |
| 51 | * Add a job to the list of ongoing tasks. It is used to allow the user to act | |
| 52 | * on the job and stop/pause a running process. | |
| 53 | * @param elementDatabase component associated to the active job | |
| 54 | * @param suspendable active job to act on | |
| 55 | */ | |
| 56 | public void put(AbstractElementDatabase elementDatabase, AbstractSuspendable suspendable) { | |
| 57 | this.suspendables.put(elementDatabase, suspendable); | |
| 58 | } | |
| 59 | | |
| 60 | /** | |
| 61 | * Get the task associated to the database component. | |
| 62 | * It's usually done to act on the task like stop/pause the corresponding process, or | |
| 63 | * to check the status of the job. | |
| 64 | * @param elementDatabase component associated to the active job | |
| 65 | * @return job currently running | |
| 66 | */ | |
| 67 | public AbstractSuspendable get(AbstractElementDatabase elementDatabase) { | |
| 68 |
1
1. get : replaced return value with null for com/jsql/util/ThreadUtil::get → NO_COVERAGE |
return this.suspendables.get(elementDatabase); |
| 69 | } | |
| 70 | | |
| 71 | /** | |
| 72 | * Remove the thread corresponding to the component in order to be | |
| 73 | * garbage collected. The thread should be stopped prior the deletion. | |
| 74 | * @param elementDatabase component associated to thread | |
| 75 | */ | |
| 76 | public void remove(AbstractElementDatabase elementDatabase) { | |
| 77 | this.suspendables.remove(elementDatabase); | |
| 78 | } | |
| 79 | | |
| 80 | /** | |
| 81 | * Force to stop every threads still running and empty the list where | |
| 82 | * they were instantiated in order to be garbage collected. | |
| 83 | */ | |
| 84 | public void reset() { | |
| 85 |
1
1. reset : removed call to java/util/Collection::forEach → NO_COVERAGE |
this.suspendables.values().forEach(AbstractSuspendable::stop); |
| 86 |
1
1. reset : removed call to java/util/Map::clear → NO_COVERAGE |
this.suspendables.clear(); |
| 87 | } | |
| 88 | | |
| 89 | public ExecutorService getExecutor(String nameThread) { | |
| 90 | ExecutorService taskExecutor; | |
| 91 | | |
| 92 |
1
1. getExecutor : negated conditional → NO_COVERAGE |
if (this.injectionModel.getMediatorUtils().getPreferencesUtil().isLimitingThreads()) { |
| 93 | int countThreads = this.injectionModel.getMediatorUtils().getPreferencesUtil().countLimitingThreads(); | |
| 94 | taskExecutor = Executors.newFixedThreadPool(countThreads, new ThreadFactoryCallable(nameThread)); | |
| 95 | } else { | |
| 96 | taskExecutor = Executors.newCachedThreadPool(new ThreadFactoryCallable(nameThread)); | |
| 97 | } | |
| 98 |
1
1. getExecutor : replaced return value with null for com/jsql/util/ThreadUtil::getExecutor → NO_COVERAGE |
return taskExecutor; |
| 99 | } | |
| 100 | ||
| 101 | public void shutdown(ExecutorService taskExecutor) { | |
| 102 | int timeout = 15; | |
| 103 |
1
1. shutdown : negated conditional → NO_COVERAGE |
if (this.injectionModel.getMediatorUtils().getPreferencesUtil().isConnectionTimeout()) { |
| 104 | timeout = this.injectionModel.getMediatorUtils().getPreferencesUtil().countConnectionTimeout(); | |
| 105 | } | |
| 106 | ||
| 107 | try { | |
| 108 |
1
1. shutdown : removed call to java/util/concurrent/ExecutorService::shutdown → NO_COVERAGE |
taskExecutor.shutdown(); |
| 109 |
1
1. shutdown : negated conditional → NO_COVERAGE |
if (!taskExecutor.awaitTermination(timeout, TimeUnit.SECONDS)) { |
| 110 | taskExecutor.shutdownNow(); | |
| 111 | } | |
| 112 | } catch (InterruptedException e) { | |
| 113 | LOGGER.log(LogLevelUtil.IGNORE, e, e); | |
| 114 |
1
1. shutdown : removed call to java/lang/Thread::interrupt → NO_COVERAGE |
Thread.currentThread().interrupt(); |
| 115 | } | |
| 116 | } | |
| 117 | } | |
Mutations | ||
| 68 |
1.1 |
|
| 85 |
1.1 |
|
| 86 |
1.1 |
|
| 92 |
1.1 |
|
| 98 |
1.1 |
|
| 103 |
1.1 |
|
| 108 |
1.1 |
|
| 109 |
1.1 |
|
| 114 |
1.1 |