ThreadUtil.java

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
    /**
36
     * Log4j logger sent to view.
37
     */
38
    private static final Logger LOGGER = LogManager.getRootLogger();
39
    
40
    /**
41
     * List of running jobs associated to a database injection task.
42
     * We can interact with those tasks in order to pause/resume and stop the process.
43
     */
44
    // Fix #8258: ConcurrentModificationException on java.util.HashMap$ValueIterator.next()
45
    private final Map<AbstractElementDatabase, AbstractSuspendable> suspendables = new ConcurrentHashMap<>(new HashMap<>());
46
47
    private final InjectionModel injectionModel;
48
    
49
    public ThreadUtil(InjectionModel injectionModel) {
50
        this.injectionModel = injectionModel;
51
    }
52
53
    /**
54
     * Add a job to the list of ongoing tasks. It is used to allow the user to act
55
     * on the job and stop/pause a running process.
56
     * @param elementDatabase component associated to the active job
57
     * @param suspendable active job to act on
58
     */
59
    public void put(AbstractElementDatabase elementDatabase, AbstractSuspendable suspendable) {
60
        this.suspendables.put(elementDatabase, suspendable);
61
    }
62
    
63
    /**
64
     * Get the task associated to the database component.
65
     * It's usually done to act on the task like stop/pause the corresponding process, or
66
     * to check the status of the job.
67
     * @param elementDatabase component associated to the active job
68
     * @return job currently running
69
     */
70
    public AbstractSuspendable get(AbstractElementDatabase elementDatabase) {
71 1 1. get : replaced return value with null for com/jsql/util/ThreadUtil::get → NO_COVERAGE
        return this.suspendables.get(elementDatabase);
72
    }
73
    
74
    /**
75
     * Remove the thread corresponding to the component in order to be
76
     * garbage collected. The thread should be stopped prior the deletion.
77
     * @param elementDatabase component associated to thread
78
     */
79
    public void remove(AbstractElementDatabase elementDatabase) {
80
        this.suspendables.remove(elementDatabase);
81
    }
82
    
83
    /**
84
     * Force to stop every threads still running and empty the list where
85
     * they were instantiated in order to be garbage collected.
86
     */
87
    public void reset() {
88 1 1. reset : removed call to java/util/Collection::forEach → NO_COVERAGE
        this.suspendables.values().forEach(AbstractSuspendable::stop);
89 1 1. reset : removed call to java/util/Map::clear → NO_COVERAGE
        this.suspendables.clear();
90
    }
91
    
92
    public ExecutorService getExecutor(String nameThread) {
93
        ExecutorService taskExecutor;
94
        
95 1 1. getExecutor : negated conditional → NO_COVERAGE
        if (this.injectionModel.getMediatorUtils().getPreferencesUtil().isLimitingThreads()) {
96
            int countThreads = this.injectionModel.getMediatorUtils().getPreferencesUtil().countLimitingThreads();
97
            taskExecutor = Executors.newFixedThreadPool(countThreads, new ThreadFactoryCallable(nameThread));
98
        } else {
99
            taskExecutor = Executors.newCachedThreadPool(new ThreadFactoryCallable(nameThread));
100
        }
101 1 1. getExecutor : replaced return value with null for com/jsql/util/ThreadUtil::getExecutor → NO_COVERAGE
        return taskExecutor;
102
    }
103
104
    public void shutdown(ExecutorService taskExecutor) {
105
        int timeout = 15;
106 1 1. shutdown : negated conditional → NO_COVERAGE
        if (this.injectionModel.getMediatorUtils().getPreferencesUtil().isConnectionTimeout()) {
107
            timeout = this.injectionModel.getMediatorUtils().getPreferencesUtil().countConnectionTimeout();
108
        }
109
110
        try {
111 1 1. shutdown : removed call to java/util/concurrent/ExecutorService::shutdown → NO_COVERAGE
            taskExecutor.shutdown();
112 1 1. shutdown : negated conditional → NO_COVERAGE
            if (!taskExecutor.awaitTermination(timeout, TimeUnit.SECONDS)) {
113
                taskExecutor.shutdownNow();
114
            }
115
        } catch (InterruptedException e) {
116
            LOGGER.log(LogLevelUtil.IGNORE, e, e);
117 1 1. shutdown : removed call to java/lang/Thread::interrupt → NO_COVERAGE
            Thread.currentThread().interrupt();
118
        }
119
    }
120
}

Mutations

71

1.1
Location : get
Killed by : none
replaced return value with null for com/jsql/util/ThreadUtil::get → NO_COVERAGE

88

1.1
Location : reset
Killed by : none
removed call to java/util/Collection::forEach → NO_COVERAGE

89

1.1
Location : reset
Killed by : none
removed call to java/util/Map::clear → NO_COVERAGE

95

1.1
Location : getExecutor
Killed by : none
negated conditional → NO_COVERAGE

101

1.1
Location : getExecutor
Killed by : none
replaced return value with null for com/jsql/util/ThreadUtil::getExecutor → NO_COVERAGE

106

1.1
Location : shutdown
Killed by : none
negated conditional → NO_COVERAGE

111

1.1
Location : shutdown
Killed by : none
removed call to java/util/concurrent/ExecutorService::shutdown → NO_COVERAGE

112

1.1
Location : shutdown
Killed by : none
negated conditional → NO_COVERAGE

117

1.1
Location : shutdown
Killed by : none
removed call to java/lang/Thread::interrupt → NO_COVERAGE

Active mutators

Tests examined


Report generated by PIT 1.19.1