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