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.view.swing; | |
12 | ||
13 | import com.jsql.model.InjectionModel; | |
14 | import com.jsql.util.*; | |
15 | import com.jsql.view.interaction.SubscriberInteraction; | |
16 | import com.jsql.view.swing.action.HotkeyUtil; | |
17 | import com.jsql.view.swing.menubar.AppMenubar; | |
18 | import com.jsql.view.swing.panel.PanelAddressBar; | |
19 | import com.jsql.view.swing.panel.split.SplitNS; | |
20 | import com.jsql.view.swing.terminal.AbstractExploit; | |
21 | import com.jsql.view.swing.tab.TabManagers; | |
22 | import com.jsql.view.swing.util.MediatorHelper; | |
23 | import com.jsql.view.swing.util.UiUtil; | |
24 | import org.apache.commons.lang3.SystemUtils; | |
25 | import org.apache.logging.log4j.LogManager; | |
26 | import org.apache.logging.log4j.Logger; | |
27 | ||
28 | import javax.swing.*; | |
29 | import java.awt.*; | |
30 | import java.awt.event.WindowAdapter; | |
31 | import java.awt.event.WindowEvent; | |
32 | import java.math.BigDecimal; | |
33 | import java.math.RoundingMode; | |
34 | import java.util.HashMap; | |
35 | import java.util.Map; | |
36 | import java.util.UUID; | |
37 | import java.util.prefs.Preferences; | |
38 | import java.util.stream.Stream; | |
39 | ||
40 | /** | |
41 | * View in the MVC pattern, defines all the components | |
42 | * and process actions sent by the model.<br> | |
43 | * Main groups of components:<br> | |
44 | * - at the top: textfield inputs,<br> | |
45 | * - at the center: tree on the left, table on the right,<br> | |
46 | * - at the bottom: information labels. | |
47 | */ | |
48 | public class JFrameView extends JFrame { | |
49 | ||
50 | /** | |
51 | * Log4j logger sent to view. | |
52 | */ | |
53 | private static final Logger LOGGER = LogManager.getRootLogger(); | |
54 | ||
55 | /** | |
56 | * Map of terminal by unique identifier. | |
57 | */ | |
58 | private final Map<UUID, AbstractExploit> mapUuidShell = new HashMap<>(); | |
59 | private final transient SubscriberInteraction subscriber = new SubscriberInteraction("com.jsql.view.swing.interaction"); | |
60 | private TabManagers tabManagers; | |
61 | private boolean isMaximized = false; | |
62 | private final InjectionModel injectionModel; | |
63 | private SplitNS splitNS; // main | |
64 | ||
65 | public JFrameView(InjectionModel injectionModel) { // Build the GUI: add app icon, tree icons, the 3 main panels | |
66 | super(StringUtil.APP_NAME); | |
67 | this.injectionModel = injectionModel; | |
68 |
1
1. <init> : removed call to com/jsql/view/swing/util/MediatorHelper::register → NO_COVERAGE |
MediatorHelper.register(this); |
69 |
1
1. <init> : removed call to com/jsql/view/swing/util/UiUtil::prepareGUI → NO_COVERAGE |
UiUtil.prepareGUI(); // Load UI before any component |
70 |
1
1. <init> : removed call to com/jsql/view/swing/JFrameView::initPaneComponents → NO_COVERAGE |
this.initPaneComponents(); |
71 |
1
1. <init> : removed call to com/jsql/view/swing/JFrameView::initWindow → NO_COVERAGE |
this.initWindow(); |
72 |
1
1. <init> : removed call to com/jsql/view/swing/JFrameView::initShortcuts → NO_COVERAGE |
this.initShortcuts(); |
73 |
1
1. <init> : removed call to com/jsql/view/swing/JFrameView::displayVersion → NO_COVERAGE |
this.displayVersion(); |
74 |
1
1. <init> : removed call to com/jsql/util/I18nUtil::checkCurrentLanguage → NO_COVERAGE |
I18nUtil.checkCurrentLanguage(); |
75 |
1
1. <init> : removed call to com/jsql/view/swing/JFrameView::check4K → NO_COVERAGE |
this.check4K(); |
76 | ||
77 |
1
1. <init> : removed call to javax/swing/SwingUtilities::invokeLater → NO_COVERAGE |
SwingUtilities.invokeLater(() -> { // paint native blu svg in theme color behind scene |
78 |
1
1. lambda$new$0 : removed call to com/jsql/view/swing/menubar/AppMenubar::applyTheme → NO_COVERAGE |
AppMenubar.applyTheme(injectionModel.getMediatorUtils().getPreferencesUtil().getThemeFlatLafName()); // refresh missing components |
79 |
1
1. lambda$new$0 : negated conditional → NO_COVERAGE |
if (injectionModel.getMediatorUtils().getProxyUtil().isNotLive(GitUtil.ShowOnConsole.YES)) { // network access |
80 | return; | |
81 | } | |
82 |
1
1. lambda$new$0 : negated conditional → NO_COVERAGE |
if (injectionModel.getMediatorUtils().getPreferencesUtil().isCheckingUpdate()) { |
83 |
1
1. lambda$new$0 : removed call to com/jsql/util/GitUtil::checkUpdate → NO_COVERAGE |
injectionModel.getMediatorUtils().getGitUtil().checkUpdate(GitUtil.ShowOnConsole.NO); |
84 | } | |
85 |
1
1. lambda$new$0 : removed call to com/jsql/util/GitUtil::showNews → NO_COVERAGE |
injectionModel.getMediatorUtils().getGitUtil().showNews(); |
86 |
1
1. lambda$new$0 : removed call to com/jsql/view/swing/JFrameView::setVisible → NO_COVERAGE |
this.setVisible(true); |
87 | MediatorHelper.panelAddressBar().getTextFieldAddress().requestFocusInWindow(); // required here to get focus | |
88 | }); | |
89 | } | |
90 | ||
91 | private void initPaneComponents() { | |
92 | // Define the default panel: each component on a vertical line | |
93 |
1
1. initPaneComponents : removed call to java/awt/Container::setLayout → NO_COVERAGE |
this.getContentPane().setLayout(new BoxLayout(this.getContentPane(), BoxLayout.PAGE_AXIS)); |
94 | ||
95 | this.tabManagers = new TabManagers(); // Tab manager linked to cards | |
96 | this.add(this.tabManagers); | |
97 | ||
98 | var menubar = new AppMenubar(); | |
99 |
1
1. initPaneComponents : removed call to com/jsql/view/swing/JFrameView::setJMenuBar → NO_COVERAGE |
this.setJMenuBar(menubar); |
100 |
1
1. initPaneComponents : removed call to com/jsql/view/swing/util/MediatorHelper::register → NO_COVERAGE |
MediatorHelper.register(menubar); |
101 | ||
102 | var panelAddressBar = new PanelAddressBar(); // Textfield at the top | |
103 |
1
1. initPaneComponents : removed call to com/jsql/view/swing/util/MediatorHelper::register → NO_COVERAGE |
MediatorHelper.register(panelAddressBar); |
104 | this.add(panelAddressBar); | |
105 | ||
106 | var mainPanel = new JPanel(new BorderLayout()); // Main panel for tree and tables in the middle | |
107 | this.splitNS = new SplitNS(); | |
108 | mainPanel.add(this.splitNS); | |
109 | this.add(mainPanel); | |
110 | ||
111 |
1
1. initPaneComponents : removed call to com/jsql/view/swing/menubar/MenuWindows::switchLocaleFromPreferences → NO_COVERAGE |
menubar.getMenuWindows().switchLocaleFromPreferences(); |
112 | } | |
113 | ||
114 | private void initWindow() { | |
115 |
1
1. initWindow : removed call to com/jsql/view/swing/JFrameView::setIconImages → NO_COVERAGE |
this.setIconImages(UiUtil.getIcons()); // define small and large app icons |
116 | var preferences = Preferences.userRoot().node(InjectionModel.class.getName()); | |
117 |
3
1. lambda$initWindow$1 : Replaced bitwise AND with OR → NO_COVERAGE 2. initWindow : removed call to com/jsql/view/swing/JFrameView::addWindowStateListener → NO_COVERAGE 3. lambda$initWindow$1 : negated conditional → NO_COVERAGE |
this.addWindowStateListener(e -> this.isMaximized = (e.getNewState() & Frame.MAXIMIZED_BOTH) == Frame.MAXIMIZED_BOTH); |
118 |
1
1. initWindow : removed call to com/jsql/view/swing/JFrameView::addWindowListener → NO_COVERAGE |
this.addWindowListener(new WindowAdapter() { |
119 | @Override | |
120 | public void windowOpened(WindowEvent event) { | |
121 |
1
1. windowOpened : negated conditional → NO_COVERAGE |
if (preferences.getBoolean(PreferencesUtil.IS_MAXIMIZED, false)) { |
122 |
1
1. windowOpened : removed call to com/jsql/view/swing/JFrameView::setExtendedState → NO_COVERAGE |
JFrameView.this.setExtendedState(Frame.MAXIMIZED_BOTH); |
123 | } | |
124 | var horizontalTopBottomSplitter = preferences.getDouble(PreferencesUtil.NS_SPLIT, 0.75); | |
125 |
4
1. windowOpened : changed conditional boundary → NO_COVERAGE 2. windowOpened : negated conditional → NO_COVERAGE 3. windowOpened : negated conditional → NO_COVERAGE 4. windowOpened : changed conditional boundary → NO_COVERAGE |
if (!(0.0 <= horizontalTopBottomSplitter && horizontalTopBottomSplitter <= 1.0)) { |
126 | horizontalTopBottomSplitter = 0.75; | |
127 | } | |
128 |
1
1. windowOpened : removed call to com/jsql/view/swing/panel/split/SplitNS::setDividerLocation → NO_COVERAGE |
JFrameView.this.splitNS.setDividerLocation(horizontalTopBottomSplitter); |
129 | } | |
130 | ||
131 | @Override | |
132 | public void windowClosing(WindowEvent e) { | |
133 |
1
1. windowClosing : removed call to java/util/prefs/Preferences::putBoolean → NO_COVERAGE |
preferences.putBoolean(PreferencesUtil.IS_MAXIMIZED, JFrameView.this.isMaximized); |
134 |
1
1. windowClosing : removed call to java/util/prefs/Preferences::putInt → NO_COVERAGE |
preferences.putInt( |
135 | PreferencesUtil.EW_SPLIT, | |
136 | // TODO not compatible arabic location | |
137 | JFrameView.this.splitNS.getSplitEW().getDividerLocation() | |
138 | ); | |
139 | | |
140 | var percentTopBottom = BigDecimal.valueOf( | |
141 |
1
1. windowClosing : Replaced double multiplication with division → NO_COVERAGE |
JFrameView.this.splitNS.getDividerLocation() * 100.0 |
142 |
2
1. windowClosing : Replaced double division with multiplication → NO_COVERAGE 2. windowClosing : Replaced double division with multiplication → NO_COVERAGE |
/ JFrameView.this.splitNS.getHeight() |
143 | / 100 | |
144 | ); | |
145 | percentTopBottom = percentTopBottom.setScale(2, RoundingMode.HALF_UP); | |
146 | | |
147 | // Divider location change when window is maximized, we can't save getDividerLocation() | |
148 |
1
1. windowClosing : removed call to java/util/prefs/Preferences::putDouble → NO_COVERAGE |
preferences.putDouble( |
149 | PreferencesUtil.NS_SPLIT, | |
150 |
1
1. windowClosing : Replaced double subtraction with addition → NO_COVERAGE |
percentTopBottom.doubleValue() - 0.01 // Fix scale |
151 | ); | |
152 | ||
153 |
1
1. windowClosing : removed call to java/util/prefs/Preferences::putBoolean → NO_COVERAGE |
preferences.putBoolean(PreferencesUtil.BINARY_VISIBLE, false); |
154 |
1
1. windowClosing : removed call to java/util/prefs/Preferences::putBoolean → NO_COVERAGE |
preferences.putBoolean(PreferencesUtil.CHUNK_VISIBLE, false); |
155 |
1
1. windowClosing : removed call to java/util/prefs/Preferences::putBoolean → NO_COVERAGE |
preferences.putBoolean(PreferencesUtil.NETWORK_VISIBLE, false); |
156 |
1
1. windowClosing : removed call to java/util/prefs/Preferences::putBoolean → NO_COVERAGE |
preferences.putBoolean(PreferencesUtil.JAVA_VISIBLE, false); |
157 |
2
1. windowClosing : changed conditional boundary → NO_COVERAGE 2. windowClosing : negated conditional → NO_COVERAGE |
for (var i = 0 ; i < MediatorHelper.tabConsoles().getTabCount() ; i++) { |
158 |
1
1. windowClosing : negated conditional → NO_COVERAGE |
if ("CONSOLE_BINARY_LABEL".equals(MediatorHelper.tabConsoles().getTabComponentAt(i).getName())) { |
159 |
1
1. windowClosing : removed call to java/util/prefs/Preferences::putBoolean → NO_COVERAGE |
preferences.putBoolean(PreferencesUtil.BINARY_VISIBLE, true); |
160 |
1
1. windowClosing : negated conditional → NO_COVERAGE |
} else if ("CONSOLE_CHUNK_LABEL".equals(MediatorHelper.tabConsoles().getTabComponentAt(i).getName())) { |
161 |
1
1. windowClosing : removed call to java/util/prefs/Preferences::putBoolean → NO_COVERAGE |
preferences.putBoolean(PreferencesUtil.CHUNK_VISIBLE, true); |
162 |
1
1. windowClosing : negated conditional → NO_COVERAGE |
} else if ("CONSOLE_NETWORK_LABEL".equals(MediatorHelper.tabConsoles().getTabComponentAt(i).getName())) { |
163 |
1
1. windowClosing : removed call to java/util/prefs/Preferences::putBoolean → NO_COVERAGE |
preferences.putBoolean(PreferencesUtil.NETWORK_VISIBLE, true); |
164 |
1
1. windowClosing : negated conditional → NO_COVERAGE |
} else if ("CONSOLE_JAVA_LABEL".equals(MediatorHelper.tabConsoles().getTabComponentAt(i).getName())) { |
165 |
1
1. windowClosing : removed call to java/util/prefs/Preferences::putBoolean → NO_COVERAGE |
preferences.putBoolean(PreferencesUtil.JAVA_VISIBLE, true); |
166 | } | |
167 | } | |
168 | } | |
169 | }); | |
170 | | |
171 |
1
1. initWindow : removed call to com/jsql/view/swing/JFrameView::setSize → NO_COVERAGE |
this.setSize(1024, 768); |
172 |
1
1. initWindow : removed call to com/jsql/view/swing/JFrameView::setLocationRelativeTo → NO_COVERAGE |
this.setLocationRelativeTo(null); // center the window |
173 |
1
1. initWindow : removed call to com/jsql/view/swing/JFrameView::setDefaultCloseOperation → NO_COVERAGE |
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); |
174 | } | |
175 | ||
176 | private void initShortcuts() { | |
177 |
1
1. initShortcuts : removed call to com/jsql/view/swing/action/HotkeyUtil::addShortcut → NO_COVERAGE |
HotkeyUtil.addShortcut(this.getRootPane(), MediatorHelper.tabResults()); |
178 |
1
1. initShortcuts : removed call to com/jsql/view/swing/action/HotkeyUtil::addTextFieldShortcutSelectAll → NO_COVERAGE |
HotkeyUtil.addTextFieldShortcutSelectAll(); |
179 | } | |
180 | ||
181 | public void resetInterface() { // Empty the interface | |
182 |
1
1. resetInterface : removed call to java/util/Map::clear → NO_COVERAGE |
this.mapUuidShell.clear(); |
183 |
1
1. resetInterface : removed call to com/jsql/view/swing/panel/address/PanelTrailingAddress::reset → NO_COVERAGE |
MediatorHelper.panelAddressBar().getPanelTrailingAddress().reset(); |
184 |
1
1. resetInterface : removed call to com/jsql/view/swing/panel/PanelConsoles::reset → NO_COVERAGE |
MediatorHelper.panelConsoles().reset(); |
185 |
1
1. resetInterface : removed call to com/jsql/view/swing/tree/TreeDatabase::reset → NO_COVERAGE |
MediatorHelper.treeDatabase().reset(); |
186 | | |
187 |
2
1. resetInterface : negated conditional → NO_COVERAGE 2. resetInterface : changed conditional boundary → NO_COVERAGE |
for (var i = 0 ; i < MediatorHelper.tabConsoles().getTabCount() ; i++) { |
188 | var tabComponent = MediatorHelper.tabConsoles().getTabComponentAt(i); | |
189 |
1
1. resetInterface : negated conditional → NO_COVERAGE |
if (tabComponent != null) { |
190 |
1
1. resetInterface : removed call to java/awt/Component::setFont → NO_COVERAGE |
tabComponent.setFont(tabComponent.getFont().deriveFont(Font.PLAIN)); |
191 | } | |
192 | } | |
193 | | |
194 |
1
1. resetInterface : removed call to java/util/stream/Stream::forEach → NO_COVERAGE |
Stream.of(MediatorHelper.managerFile(), MediatorHelper.managerExploit()).forEach(managerList -> { |
195 |
1
1. lambda$resetInterface$2 : removed call to com/jsql/view/swing/manager/AbstractManagerList::setButtonEnable → NO_COVERAGE |
managerList.setButtonEnable(false); |
196 |
1
1. lambda$resetInterface$2 : removed call to com/jsql/view/swing/manager/AbstractManagerList::changePrivilegeIcon → NO_COVERAGE |
managerList.changePrivilegeIcon(UiUtil.SQUARE.getIcon()); |
197 | }); | |
198 | } | |
199 | ||
200 | private void displayVersion() { | |
201 | LOGGER.log( | |
202 | LogLevelUtil.CONSOLE_DEFAULT, | |
203 | "{} v{} on Java {}-{}-{}", | |
204 |
1
1. lambda$displayVersion$3 : replaced return value with null for com/jsql/view/swing/JFrameView::lambda$displayVersion$3 → NO_COVERAGE |
() -> StringUtil.APP_NAME, |
205 |
1
1. lambda$displayVersion$4 : replaced return value with null for com/jsql/view/swing/JFrameView::lambda$displayVersion$4 → NO_COVERAGE |
() -> this.injectionModel.getPropertiesUtil().getVersionJsql(), |
206 |
1
1. lambda$displayVersion$5 : replaced return value with null for com/jsql/view/swing/JFrameView::lambda$displayVersion$5 → NO_COVERAGE |
() -> SystemUtils.JAVA_VERSION, |
207 |
1
1. lambda$displayVersion$6 : replaced return value with null for com/jsql/view/swing/JFrameView::lambda$displayVersion$6 → NO_COVERAGE |
() -> SystemUtils.OS_ARCH, |
208 |
1
1. lambda$displayVersion$7 : replaced return value with null for com/jsql/view/swing/JFrameView::lambda$displayVersion$7 → NO_COVERAGE |
() -> SystemUtils.USER_LANGUAGE |
209 | ); | |
210 | } | |
211 | ||
212 | private void check4K() { | |
213 | Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); | |
214 | int width = (int) screenSize.getWidth(); | |
215 |
3
1. check4K : changed conditional boundary → NO_COVERAGE 2. check4K : negated conditional → NO_COVERAGE 3. check4K : negated conditional → NO_COVERAGE |
if (width >= 3840 && !this.injectionModel.getMediatorUtils().getPreferencesUtil().is4K()) { |
216 | LOGGER.log(LogLevelUtil.CONSOLE_ERROR, "Screen compatible with resolution 4K, enable high-definition in Preferences"); | |
217 | } | |
218 | } | |
219 | ||
220 | ||
221 | // Getters and setters | |
222 | ||
223 | public final Map<UUID, AbstractExploit> getMapUuidShell() { | |
224 |
1
1. getMapUuidShell : replaced return value with Collections.emptyMap for com/jsql/view/swing/JFrameView::getMapUuidShell → NO_COVERAGE |
return this.mapUuidShell; |
225 | } | |
226 | ||
227 | public SubscriberInteraction getSubscriber() { | |
228 |
1
1. getSubscriber : replaced return value with null for com/jsql/view/swing/JFrameView::getSubscriber → NO_COVERAGE |
return this.subscriber; |
229 | } | |
230 | ||
231 | public SplitNS getSplitNS() { | |
232 |
1
1. getSplitNS : replaced return value with null for com/jsql/view/swing/JFrameView::getSplitNS → NO_COVERAGE |
return this.splitNS; |
233 | } | |
234 | ||
235 | public TabManagers getTabManagers() { | |
236 |
1
1. getTabManagers : replaced return value with null for com/jsql/view/swing/JFrameView::getTabManagers → NO_COVERAGE |
return this.tabManagers; |
237 | } | |
238 | } | |
Mutations | ||
68 |
1.1 |
|
69 |
1.1 |
|
70 |
1.1 |
|
71 |
1.1 |
|
72 |
1.1 |
|
73 |
1.1 |
|
74 |
1.1 |
|
75 |
1.1 |
|
77 |
1.1 |
|
78 |
1.1 |
|
79 |
1.1 |
|
82 |
1.1 |
|
83 |
1.1 |
|
85 |
1.1 |
|
86 |
1.1 |
|
93 |
1.1 |
|
99 |
1.1 |
|
100 |
1.1 |
|
103 |
1.1 |
|
111 |
1.1 |
|
115 |
1.1 |
|
117 |
1.1 2.2 3.3 |
|
118 |
1.1 |
|
121 |
1.1 |
|
122 |
1.1 |
|
125 |
1.1 2.2 3.3 4.4 |
|
128 |
1.1 |
|
133 |
1.1 |
|
134 |
1.1 |
|
141 |
1.1 |
|
142 |
1.1 2.2 |
|
148 |
1.1 |
|
150 |
1.1 |
|
153 |
1.1 |
|
154 |
1.1 |
|
155 |
1.1 |
|
156 |
1.1 |
|
157 |
1.1 2.2 |
|
158 |
1.1 |
|
159 |
1.1 |
|
160 |
1.1 |
|
161 |
1.1 |
|
162 |
1.1 |
|
163 |
1.1 |
|
164 |
1.1 |
|
165 |
1.1 |
|
171 |
1.1 |
|
172 |
1.1 |
|
173 |
1.1 |
|
177 |
1.1 |
|
178 |
1.1 |
|
182 |
1.1 |
|
183 |
1.1 |
|
184 |
1.1 |
|
185 |
1.1 |
|
187 |
1.1 2.2 |
|
189 |
1.1 |
|
190 |
1.1 |
|
194 |
1.1 |
|
195 |
1.1 |
|
196 |
1.1 |
|
204 |
1.1 |
|
205 |
1.1 |
|
206 |
1.1 |
|
207 |
1.1 |
|
208 |
1.1 |
|
215 |
1.1 2.2 3.3 |
|
224 |
1.1 |
|
228 |
1.1 |
|
232 |
1.1 |
|
236 |
1.1 |