1 | /******************************************************************************* | |
2 | * Copyhacked (H) 2012-2020. | |
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 about 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.I18nUtil; | |
15 | import com.jsql.view.interaction.SubscriberInteraction; | |
16 | import com.jsql.view.swing.action.HotkeyUtil; | |
17 | import com.jsql.view.swing.menubar.Menubar; | |
18 | import com.jsql.view.swing.panel.PanelAddressBar; | |
19 | import com.jsql.view.swing.panel.split.SplitHorizontalTopBottom; | |
20 | import com.jsql.view.swing.shadow.ShadowPopupFactory; | |
21 | import com.jsql.view.swing.shell.AbstractShell; | |
22 | import com.jsql.view.swing.tab.TabManagers; | |
23 | import com.jsql.view.swing.util.MediatorHelper; | |
24 | import com.jsql.view.swing.util.UiUtil; | |
25 | ||
26 | import javax.swing.*; | |
27 | import java.awt.*; | |
28 | import java.awt.event.WindowAdapter; | |
29 | import java.awt.event.WindowEvent; | |
30 | import java.math.BigDecimal; | |
31 | import java.math.RoundingMode; | |
32 | import java.util.HashMap; | |
33 | import java.util.Locale; | |
34 | import java.util.Map; | |
35 | import java.util.UUID; | |
36 | import java.util.prefs.Preferences; | |
37 | import java.util.stream.Stream; | |
38 | ||
39 | /** | |
40 | * View in the MVC pattern, defines all the components | |
41 | * and process actions sent by the model.<br> | |
42 | * Main groups of components:<br> | |
43 | * - at the top: textfield inputs,<br> | |
44 | * - at the center: tree on the left, table on the right,<br> | |
45 | * - at the bottom: information labels. | |
46 | */ | |
47 | public class JFrameView extends JFrame { | |
48 | ||
49 | // Main center panel | |
50 | private SplitHorizontalTopBottom splitHorizontalTopBottom; | |
51 | ||
52 | // List of terminal by unique identifier | |
53 | private final Map<UUID, AbstractShell> mapShells = new HashMap<>(); | |
54 | | |
55 | private final transient SubscriberInteraction subscriber = new SubscriberInteraction("com.jsql.view.swing.interaction"); | |
56 | | |
57 | // Build the GUI: add app icon, tree icons, the 3 main panels | |
58 | public JFrameView() { | |
59 | | |
60 | super("jSQL Injection"); | |
61 | | |
62 |
1
1. <init> : removed call to com/jsql/view/swing/util/MediatorHelper::register → NO_COVERAGE |
MediatorHelper.register(this); |
63 | ||
64 | // Load UI before any component | |
65 |
1
1. <init> : removed call to com/jsql/view/swing/util/UiUtil::prepareGUI → NO_COVERAGE |
UiUtil.prepareGUI(); |
66 |
1
1. <init> : removed call to com/jsql/view/swing/shadow/ShadowPopupFactory::install → NO_COVERAGE |
ShadowPopupFactory.install(); |
67 | | |
68 |
1
1. <init> : removed call to com/jsql/view/swing/JFrameView::initializePaneComponents → NO_COVERAGE |
this.initializePaneComponents(); |
69 |
1
1. <init> : removed call to com/jsql/view/swing/JFrameView::initializeWindow → NO_COVERAGE |
this.initializeWindow(); |
70 |
1
1. <init> : removed call to com/jsql/view/swing/JFrameView::initializeShortcuts → NO_COVERAGE |
this.initializeShortcuts(); |
71 | } | |
72 | ||
73 | private void initializeWindow() { | |
74 | | |
75 | // Define a small and large app icon | |
76 |
1
1. initializeWindow : removed call to com/jsql/view/swing/JFrameView::setIconImages → NO_COVERAGE |
this.setIconImages(UiUtil.getIcons()); |
77 | ||
78 |
1
1. initializeWindow : removed call to com/jsql/view/swing/JFrameView::addWindowListener → NO_COVERAGE |
this.addWindowListener(new WindowAdapter() { |
79 | | |
80 | @Override | |
81 | public void windowOpened(WindowEvent event) { | |
82 | | |
83 |
1
1. windowOpened : removed call to java/awt/event/WindowAdapter::windowOpened → NO_COVERAGE |
super.windowOpened(event); |
84 | | |
85 | var preferences = Preferences.userRoot().node(InjectionModel.class.getName()); | |
86 | var horizontalTopBottomSplitter = preferences.getDouble(SplitHorizontalTopBottom.getNameHSplitpane(), 0.75); | |
87 | | |
88 |
4
1. windowOpened : changed conditional boundary → NO_COVERAGE 2. windowOpened : changed conditional boundary → NO_COVERAGE 3. windowOpened : negated conditional → NO_COVERAGE 4. windowOpened : negated conditional → NO_COVERAGE |
if (!(0.0 <= horizontalTopBottomSplitter && horizontalTopBottomSplitter <= 1.0)) { |
89 | | |
90 | horizontalTopBottomSplitter = 0.75; | |
91 | } | |
92 | ||
93 |
1
1. windowOpened : removed call to com/jsql/view/swing/panel/split/SplitHorizontalTopBottom::setDividerLocation → NO_COVERAGE |
JFrameView.this.splitHorizontalTopBottom.setDividerLocation(horizontalTopBottomSplitter); |
94 | } | |
95 | | |
96 | @Override | |
97 | public void windowClosing(WindowEvent e) { | |
98 | | |
99 | var preferences = Preferences.userRoot().node(InjectionModel.class.getName()); | |
100 |
1
1. windowClosing : removed call to java/util/prefs/Preferences::putInt → NO_COVERAGE |
preferences.putInt( |
101 | SplitHorizontalTopBottom.getNameVSplitpane(), | |
102 | JFrameView.this.splitHorizontalTopBottom.getSplitVerticalLeftRight().getDividerLocation() | |
103 | ); | |
104 | | |
105 | var roundDecimal = BigDecimal.valueOf( | |
106 |
1
1. windowClosing : Replaced double multiplication with division → NO_COVERAGE |
JFrameView.this.splitHorizontalTopBottom.getDividerLocation() * 100.0 |
107 |
2
1. windowClosing : Replaced double division with multiplication → NO_COVERAGE 2. windowClosing : Replaced double division with multiplication → NO_COVERAGE |
/ JFrameView.this.splitHorizontalTopBottom.getHeight() |
108 | / 100 | |
109 | ); | |
110 | roundDecimal = roundDecimal.setScale(2, RoundingMode.HALF_UP); | |
111 | | |
112 | // Divider location change when window is maximized, we can't save getDividerLocation() | |
113 |
1
1. windowClosing : removed call to java/util/prefs/Preferences::putDouble → NO_COVERAGE |
preferences.putDouble( |
114 | SplitHorizontalTopBottom.getNameHSplitpane(), | |
115 | // Fix scale | |
116 |
1
1. windowClosing : Replaced double subtraction with addition → NO_COVERAGE |
roundDecimal.doubleValue() - 0.01 |
117 | ); | |
118 | | |
119 |
1
1. windowClosing : removed call to java/util/prefs/Preferences::putBoolean → NO_COVERAGE |
preferences.putBoolean(UiUtil.BINARY_VISIBLE, false); |
120 |
1
1. windowClosing : removed call to java/util/prefs/Preferences::putBoolean → NO_COVERAGE |
preferences.putBoolean(UiUtil.CHUNK_VISIBLE, false); |
121 |
1
1. windowClosing : removed call to java/util/prefs/Preferences::putBoolean → NO_COVERAGE |
preferences.putBoolean(UiUtil.NETWORK_VISIBLE, false); |
122 |
1
1. windowClosing : removed call to java/util/prefs/Preferences::putBoolean → NO_COVERAGE |
preferences.putBoolean(UiUtil.JAVA_VISIBLE, false); |
123 | | |
124 |
2
1. windowClosing : changed conditional boundary → NO_COVERAGE 2. windowClosing : negated conditional → NO_COVERAGE |
for (var i = 0 ; i < MediatorHelper.tabConsoles().getTabCount() ; i++) { |
125 | | |
126 |
1
1. windowClosing : negated conditional → NO_COVERAGE |
if ("CONSOLE_BINARY_LABEL".equals(MediatorHelper.tabConsoles().getTabComponentAt(i).getName())) { |
127 | | |
128 |
1
1. windowClosing : removed call to java/util/prefs/Preferences::putBoolean → NO_COVERAGE |
preferences.putBoolean(UiUtil.BINARY_VISIBLE, true); |
129 | | |
130 |
1
1. windowClosing : negated conditional → NO_COVERAGE |
} else if ("CONSOLE_CHUNK_LABEL".equals(MediatorHelper.tabConsoles().getTabComponentAt(i).getName())) { |
131 | | |
132 |
1
1. windowClosing : removed call to java/util/prefs/Preferences::putBoolean → NO_COVERAGE |
preferences.putBoolean(UiUtil.CHUNK_VISIBLE, true); |
133 | | |
134 |
1
1. windowClosing : negated conditional → NO_COVERAGE |
} else if ("CONSOLE_NETWORK_LABEL".equals(MediatorHelper.tabConsoles().getTabComponentAt(i).getName())) { |
135 | | |
136 |
1
1. windowClosing : removed call to java/util/prefs/Preferences::putBoolean → NO_COVERAGE |
preferences.putBoolean(UiUtil.NETWORK_VISIBLE, true); |
137 | | |
138 |
1
1. windowClosing : negated conditional → NO_COVERAGE |
} else if ("CONSOLE_JAVA_LABEL".equals(MediatorHelper.tabConsoles().getTabComponentAt(i).getName())) { |
139 | | |
140 |
1
1. windowClosing : removed call to java/util/prefs/Preferences::putBoolean → NO_COVERAGE |
preferences.putBoolean(UiUtil.JAVA_VISIBLE, true); |
141 | } | |
142 | } | |
143 | } | |
144 | }); | |
145 | | |
146 | // Size of window | |
147 |
1
1. initializeWindow : removed call to com/jsql/view/swing/JFrameView::setSize → NO_COVERAGE |
this.setSize(1024, 768); |
148 |
1
1. initializeWindow : removed call to com/jsql/view/swing/JFrameView::setVisible → NO_COVERAGE |
this.setVisible(true); |
149 | ||
150 | // Center the window | |
151 |
1
1. initializeWindow : removed call to com/jsql/view/swing/JFrameView::setLocationRelativeTo → NO_COVERAGE |
this.setLocationRelativeTo(null); |
152 | | |
153 |
1
1. initializeWindow : removed call to com/jsql/view/swing/JFrameView::setVisible → NO_COVERAGE |
this.setVisible(true); |
154 |
1
1. initializeWindow : removed call to com/jsql/view/swing/JFrameView::setDefaultCloseOperation → NO_COVERAGE |
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); |
155 | | |
156 | MediatorHelper.panelAddressBar().getTextFieldAddress().requestFocusInWindow(); | |
157 | } | |
158 | ||
159 | private void initializeShortcuts() { | |
160 | | |
161 | // Define the keyword shortcuts for tabs #Need to work even if the focus is not on tabs | |
162 |
1
1. initializeShortcuts : removed call to com/jsql/view/swing/action/HotkeyUtil::addShortcut → NO_COVERAGE |
HotkeyUtil.addShortcut(this.getRootPane(), MediatorHelper.tabResults()); |
163 |
1
1. initializeShortcuts : removed call to com/jsql/view/swing/action/HotkeyUtil::addTextFieldShortcutSelectAll → NO_COVERAGE |
HotkeyUtil.addTextFieldShortcutSelectAll(); |
164 | } | |
165 | ||
166 | private void initializePaneComponents() { | |
167 | | |
168 | // Save controller | |
169 | var menubar = new Menubar(); | |
170 |
1
1. initializePaneComponents : removed call to com/jsql/view/swing/JFrameView::setJMenuBar → NO_COVERAGE |
this.setJMenuBar(menubar); |
171 |
1
1. initializePaneComponents : removed call to com/jsql/view/swing/util/MediatorHelper::register → NO_COVERAGE |
MediatorHelper.register(menubar); |
172 | | |
173 | // Define the default panel: each component on a vertical line | |
174 |
1
1. initializePaneComponents : removed call to java/awt/Container::setLayout → NO_COVERAGE |
this.getContentPane().setLayout(new BoxLayout(this.getContentPane(), BoxLayout.PAGE_AXIS)); |
175 | ||
176 | // Main panel for tree and tables in the middle | |
177 | // Set proxy tabs dependency | |
178 | var mainPanel = new JPanel(new GridLayout(1, 0)); | |
179 | this.splitHorizontalTopBottom = new SplitHorizontalTopBottom(); | |
180 | mainPanel.add(this.splitHorizontalTopBottom); | |
181 | ||
182 | var panelAddressBar = new PanelAddressBar(); // Textfields at the top | |
183 | JTabbedPane tabManagers = new TabManagers(); // Tab manager use proxy tabs dependency | |
184 | ||
185 | this.add(tabManagers); | |
186 | this.add(panelAddressBar); | |
187 |
1
1. initializePaneComponents : removed call to com/jsql/view/swing/util/MediatorHelper::register → NO_COVERAGE |
MediatorHelper.register(panelAddressBar); |
188 | ||
189 | this.add(mainPanel); | |
190 | | |
191 |
1
1. initializePaneComponents : removed call to com/jsql/view/swing/menubar/Menubar::switchLocale → NO_COVERAGE |
menubar.switchLocale(Locale.ENGLISH, I18nUtil.getLocaleDefault(), true); |
192 | } | |
193 | ||
194 | // Empty the interface | |
195 | public void resetInterface() { | |
196 | | |
197 |
1
1. resetInterface : removed call to com/jsql/view/swing/panel/address/AddressMenuBar::reset → NO_COVERAGE |
MediatorHelper.panelAddressBar().getAddressMenuBar().reset(); |
198 | | |
199 |
1
1. resetInterface : removed call to java/util/Map::clear → NO_COVERAGE |
MediatorHelper.treeDatabase().getTreeNodeModels().clear(); |
200 |
1
1. resetInterface : removed call to java/util/Map::clear → NO_COVERAGE |
this.mapShells.clear(); |
201 | | |
202 |
1
1. resetInterface : removed call to com/jsql/view/swing/panel/PanelConsoles::reset → NO_COVERAGE |
MediatorHelper.panelConsoles().reset(); |
203 |
1
1. resetInterface : removed call to com/jsql/view/swing/tree/TreeDatabase::reset → NO_COVERAGE |
MediatorHelper.treeDatabase().reset(); |
204 | | |
205 |
2
1. resetInterface : changed conditional boundary → NO_COVERAGE 2. resetInterface : negated conditional → NO_COVERAGE |
for (var i = 0 ; i < MediatorHelper.tabConsoles().getTabCount() ; i++) { |
206 | | |
207 | var tabComponent = MediatorHelper.tabConsoles().getTabComponentAt(i); | |
208 |
1
1. resetInterface : negated conditional → NO_COVERAGE |
if (tabComponent != null) { |
209 | | |
210 |
1
1. resetInterface : removed call to java/awt/Component::setFont → NO_COVERAGE |
tabComponent.setFont(tabComponent.getFont().deriveFont(Font.PLAIN)); |
211 | } | |
212 | } | |
213 | | |
214 | Stream.of( | |
215 | MediatorHelper.managerUpload(), | |
216 | MediatorHelper.managerFile(), | |
217 | MediatorHelper.managerWebshell(), | |
218 | MediatorHelper.managerSqlshell() | |
219 | ) | |
220 |
1
1. resetInterface : removed call to java/util/stream/Stream::forEach → NO_COVERAGE |
.forEach(managerList -> { |
221 | | |
222 |
1
1. lambda$resetInterface$0 : removed call to com/jsql/view/swing/manager/AbstractManagerList::setButtonEnable → NO_COVERAGE |
managerList.setButtonEnable(false); |
223 |
1
1. lambda$resetInterface$0 : removed call to com/jsql/view/swing/manager/AbstractManagerList::changePrivilegeIcon → NO_COVERAGE |
managerList.changePrivilegeIcon(UiUtil.ICON_SQUARE_GREY); |
224 | }); | |
225 | } | |
226 | | |
227 | | |
228 | // Getters and setters | |
229 | ||
230 | /** | |
231 | * Get list of terminal by unique identifier. | |
232 | * @return Map of key/value UUID => Terminal | |
233 | */ | |
234 | public final Map<UUID, AbstractShell> getConsoles() { | |
235 |
1
1. getConsoles : replaced return value with Collections.emptyMap for com/jsql/view/swing/JFrameView::getConsoles → NO_COVERAGE |
return this.mapShells; |
236 | } | |
237 | ||
238 | public SubscriberInteraction getSubscriber() { | |
239 |
1
1. getSubscriber : replaced return value with null for com/jsql/view/swing/JFrameView::getSubscriber → NO_COVERAGE |
return this.subscriber; |
240 | } | |
241 | ||
242 | public SplitHorizontalTopBottom getSplitHorizontalTopBottom() { | |
243 |
1
1. getSplitHorizontalTopBottom : replaced return value with null for com/jsql/view/swing/JFrameView::getSplitHorizontalTopBottom → NO_COVERAGE |
return this.splitHorizontalTopBottom; |
244 | } | |
245 | } | |
Mutations | ||
62 |
1.1 |
|
65 |
1.1 |
|
66 |
1.1 |
|
68 |
1.1 |
|
69 |
1.1 |
|
70 |
1.1 |
|
76 |
1.1 |
|
78 |
1.1 |
|
83 |
1.1 |
|
88 |
1.1 2.2 3.3 4.4 |
|
93 |
1.1 |
|
100 |
1.1 |
|
106 |
1.1 |
|
107 |
1.1 2.2 |
|
113 |
1.1 |
|
116 |
1.1 |
|
119 |
1.1 |
|
120 |
1.1 |
|
121 |
1.1 |
|
122 |
1.1 |
|
124 |
1.1 2.2 |
|
126 |
1.1 |
|
128 |
1.1 |
|
130 |
1.1 |
|
132 |
1.1 |
|
134 |
1.1 |
|
136 |
1.1 |
|
138 |
1.1 |
|
140 |
1.1 |
|
147 |
1.1 |
|
148 |
1.1 |
|
151 |
1.1 |
|
153 |
1.1 |
|
154 |
1.1 |
|
162 |
1.1 |
|
163 |
1.1 |
|
170 |
1.1 |
|
171 |
1.1 |
|
174 |
1.1 |
|
187 |
1.1 |
|
191 |
1.1 |
|
197 |
1.1 |
|
199 |
1.1 |
|
200 |
1.1 |
|
202 |
1.1 |
|
203 |
1.1 |
|
205 |
1.1 2.2 |
|
208 |
1.1 |
|
210 |
1.1 |
|
220 |
1.1 |
|
222 |
1.1 |
|
223 |
1.1 |
|
235 |
1.1 |
|
239 |
1.1 |
|
243 |
1.1 |