| 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 |