• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

jiangxincode / ApkToolBoxGUI / #1166

06 Sep 2025 11:06AM UTC coverage: 2.891%. Remained the same
#1166

push

jiangxincode
[PMD issues]Fix PMD issues: UnnecessaryFullyQualifiedName

3 of 27 new or added lines in 11 files covered. (11.11%)

1 existing line in 1 file now uncovered.

248 of 8579 relevant lines covered (2.89%)

0.03 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/main/java/edu/jiangxin/apktoolbox/pdf/passwordremover/PdfPasswordRemoverPanel.java
1
package edu.jiangxin.apktoolbox.pdf.passwordremover;
2

3
import edu.jiangxin.apktoolbox.pdf.PdfUtils;
4
import edu.jiangxin.apktoolbox.swing.extend.EasyPanel;
5
import edu.jiangxin.apktoolbox.swing.extend.FileListPanel;
6
import edu.jiangxin.apktoolbox.swing.extend.filepanel.FilePanel;
7
import edu.jiangxin.apktoolbox.utils.Constants;
8
import edu.jiangxin.apktoolbox.utils.FileUtils;
9

10
import javax.swing.*;
11
import java.awt.event.ActionEvent;
12
import java.awt.event.ActionListener;
13
import java.io.File;
14
import java.util.ArrayList;
15
import java.util.List;
16
import java.util.Set;
17
import java.util.TreeSet;
18
import java.util.concurrent.ExecutorService;
19
import java.util.concurrent.Executors;
20
import java.util.concurrent.Future;
21
import java.util.concurrent.atomic.AtomicInteger;
22

23
public class PdfPasswordRemoverPanel extends EasyPanel {
×
24
    private FileListPanel fileListPanel;
25

26
    private JCheckBox isRecursiveSearched;
27

28
    private FilePanel targetDirPanel;
29

30
    private JButton startButton;
31
    private JButton cancelButton;
32

33
    private JProgressBar progressBar;
34

35
    private WorkderThread searchThread;
36

37
    final private List<File> scannedFileList = new ArrayList<>();
×
38
    @Override
39
    public void initUI() {
40
        BoxLayout boxLayout = new BoxLayout(this, BoxLayout.Y_AXIS);
×
41
        setLayout(boxLayout);
×
42

43
        createInputPanel();
×
44
        add(Box.createVerticalStrut(Constants.DEFAULT_Y_BORDER));
×
45

46
        createOutputPanel();
×
47
        add(Box.createVerticalStrut(Constants.DEFAULT_Y_BORDER));
×
48

49
        createOptionPanel();
×
50
        add(Box.createVerticalStrut(Constants.DEFAULT_Y_BORDER));
×
51

52
        createOperationPanel();
×
53
        add(Box.createVerticalStrut(Constants.DEFAULT_Y_BORDER));
×
54

55
        createProcessBarPanel();
×
56
    }
×
57

58
    private void createInputPanel() {
59
        fileListPanel = new FileListPanel();
×
60
        add(fileListPanel);
×
61
    }
×
62

63
    private void createOutputPanel() {
64
        targetDirPanel = new FilePanel("Target Directory");
×
65
        targetDirPanel.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
×
66
        add(targetDirPanel);
×
67
    }
×
68

69
    private void createOptionPanel() {
70
        JPanel optionPanel = new JPanel();
×
71
        optionPanel.setLayout(new BoxLayout(optionPanel, BoxLayout.X_AXIS));
×
72
        optionPanel.setBorder(BorderFactory.createTitledBorder("Options"));
×
73

74
        isRecursiveSearched = new JCheckBox("Recursive Search");
×
75
        isRecursiveSearched.setSelected(true);
×
76
        optionPanel.add(isRecursiveSearched);
×
77
        optionPanel.add(Box.createHorizontalGlue());
×
78

79
        add(optionPanel);
×
80
    }
×
81

82
    private void createOperationPanel() {
83
        JPanel operationPanel = new JPanel();
×
84
        operationPanel.setLayout(new BoxLayout(operationPanel, BoxLayout.X_AXIS));
×
85
        operationPanel.setBorder(BorderFactory.createTitledBorder("Operations"));
×
86

87
        startButton = new JButton("Start");
×
88
        cancelButton = new JButton("Cancel");
×
89
        cancelButton.setEnabled(false);
×
90
        startButton.addActionListener(new OperationButtonActionListener());
×
91
        cancelButton.addActionListener(new OperationButtonActionListener());
×
92
        operationPanel.add(startButton);
×
93
        operationPanel.add(Box.createHorizontalStrut(Constants.DEFAULT_X_BORDER));
×
94
        operationPanel.add(Box.createHorizontalStrut(Constants.DEFAULT_X_BORDER));
×
95
        operationPanel.add(cancelButton);
×
96
        operationPanel.add(Box.createHorizontalGlue());
×
97

98
        add(operationPanel);
×
99
    }
×
100

101
    private void createProcessBarPanel() {
102
        progressBar = new JProgressBar();
×
103
        progressBar.setStringPainted(true);
×
104
        progressBar.setString("Ready");
×
105

106
        add(progressBar);
×
107
    }
×
108

109
    private void processFile(File encryptedFile, File targetDir) {
110
        try {
111
            if (Thread.currentThread().isInterrupted()) {
×
112
                return;
×
113
            }
114
            PdfUtils.removePasswordWithIText(encryptedFile, targetDir);
×
115
        } catch (Throwable t) {
×
116
            logger.error("Process file failed: {}", encryptedFile.getAbsolutePath(), t);
×
117
        }
×
118
    }
×
119

120
    class OperationButtonActionListener implements ActionListener {
×
121
        @Override
122
        public void actionPerformed(ActionEvent e) {
123
            Object source = e.getSource();
×
124
            if (source.equals(startButton)) {
×
125
                startButton.setEnabled(false);
×
126
                cancelButton.setEnabled(true);
×
127
                searchThread = new WorkderThread(isRecursiveSearched.isSelected());
×
128
                searchThread.start();
×
129
            } else if (source.equals(cancelButton)) {
×
130
                startButton.setEnabled(true);
×
131
                cancelButton.setEnabled(false);
×
132
                if (searchThread.isAlive()) {
×
133
                    searchThread.interrupt();
×
134
                    searchThread.executorService.shutdownNow();
×
135
                }
136
            }
137

138
        }
×
139
    }
140

141
    class WorkderThread extends Thread {
142
        public final ExecutorService executorService;
143
        private final AtomicInteger processedFiles = new AtomicInteger(0);
×
144
        private int totalFiles = 0;
×
145
        private final boolean isRecursiveSearched;
146

147
        public WorkderThread(boolean isRecursiveSearched) {
×
148
            super();
×
149
            this.isRecursiveSearched = isRecursiveSearched;
×
150
            this.executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
×
151

152
            SwingUtilities.invokeLater(() -> {
×
153
                progressBar.setValue(0);
×
154
                progressBar.setString("Starting remove process...");
×
155
            });
×
156
        }
×
157

158
        @Override
159
        public void run() {
160
            try {
161
                List<File> fileList = fileListPanel.getFileList();
×
162
                Set<File> fileSet = new TreeSet<>();
×
163
                String[] extensions = new String[]{"pdf", "PDF"};
×
164
                for (File file : fileList) {
×
165
                    fileSet.addAll(FileUtils.listFiles(file, extensions, isRecursiveSearched));
×
166
                }
×
167

168
                List<Future<?>> futures = new ArrayList<>();
×
169
                totalFiles = fileSet.size();
×
170
                updateProgress();
×
171

172
                for (File file : fileSet) {
×
NEW
173
                    if (currentThread().isInterrupted()) {
×
174
                        return;
×
175
                    }
176
                    futures.add(executorService.submit(() -> {
×
NEW
177
                        if (currentThread().isInterrupted()) {
×
178
                            return null;
×
179
                        }
180
                        processFile(file, targetDirPanel.getFile());
×
181
                        incrementProcessedFiles();
×
182
                        return null;
×
183
                    }));
184
                }
×
185

186
                // Wait for all tasks to complete
187
                for (Future<?> future : futures) {
×
188
                    try {
189
                        future.get();
×
190
                    } catch (InterruptedException e) {
×
191
                        logger.error("Remove process interrupted", e);
×
NEW
192
                        currentThread().interrupt(); // Restore interrupted status
×
193
                        return;
×
194
                    }
×
195
                }
×
196
            } catch (Exception e) {
×
197
                logger.error("Remove process failed", e);
×
198
                SwingUtilities.invokeLater(() -> progressBar.setString("Remove process failed"));
×
199
            } finally {
200
                executorService.shutdown();
×
201
                SwingUtilities.invokeLater(() -> {
×
202
                    startButton.setEnabled(true);
×
203
                    cancelButton.setEnabled(false);
×
204
                });
×
205
            }
206
        }
×
207

208
        private void incrementProcessedFiles() {
209
            processedFiles.incrementAndGet();
×
210
            updateProgress();
×
211
        }
×
212

213
        private void updateProgress() {
214
            if (totalFiles > 0) {
×
215
                SwingUtilities.invokeLater(() -> {
×
216
                    int processed = processedFiles.get();
×
217
                    int percentage = (int) ((processed * 100.0) / totalFiles);
×
218
                    progressBar.setValue(percentage);
×
219
                    progressBar.setString(String.format("Processing: %d/%d files (%d%%)", processed, totalFiles, percentage));
×
220
                });
×
221
            }
222
        }
×
223
    }
224
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc