Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/tools/jconsole/VMPanel.java
38918 views
1
/*
2
* Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package sun.tools.jconsole;
27
28
import java.awt.*;
29
import java.awt.event.*;
30
import java.beans.*;
31
import java.lang.reflect.*;
32
import java.util.*;
33
import java.util.List;
34
import java.util.Timer;
35
import javax.swing.*;
36
import javax.swing.plaf.*;
37
38
39
import com.sun.tools.jconsole.JConsolePlugin;
40
import com.sun.tools.jconsole.JConsoleContext;
41
42
import static sun.tools.jconsole.ProxyClient.*;
43
44
@SuppressWarnings("serial")
45
public class VMPanel extends JTabbedPane implements PropertyChangeListener {
46
47
private ProxyClient proxyClient;
48
private Timer timer;
49
private int updateInterval;
50
private String hostName;
51
private int port;
52
private String userName;
53
private String password;
54
private String url;
55
private VMInternalFrame vmIF = null;
56
private static ArrayList<TabInfo> tabInfos = new ArrayList<TabInfo>();
57
private boolean wasConnected = false;
58
private boolean userDisconnected = false;
59
private boolean shouldUseSSL = true;
60
61
// The everConnected flag keeps track of whether the window can be
62
// closed if the user clicks Cancel after a failed connection attempt.
63
//
64
private boolean everConnected = false;
65
66
// The initialUpdate flag is used to enable/disable tabs each time
67
// a connect or reconnect takes place. This flag avoids having to
68
// enable/disable tabs on each update call.
69
//
70
private boolean initialUpdate = true;
71
72
// Each VMPanel has its own instance of the JConsolePlugin
73
// A map of JConsolePlugin to the previous SwingWorker
74
private Map<ExceptionSafePlugin, SwingWorker<?, ?>> plugins = null;
75
private boolean pluginTabsAdded = false;
76
77
// Update these only on the EDT
78
private JOptionPane optionPane;
79
private JProgressBar progressBar;
80
private long time0;
81
82
static {
83
tabInfos.add(new TabInfo(OverviewTab.class, OverviewTab.getTabName(), true));
84
tabInfos.add(new TabInfo(MemoryTab.class, MemoryTab.getTabName(), true));
85
tabInfos.add(new TabInfo(ThreadTab.class, ThreadTab.getTabName(), true));
86
tabInfos.add(new TabInfo(ClassTab.class, ClassTab.getTabName(), true));
87
tabInfos.add(new TabInfo(SummaryTab.class, SummaryTab.getTabName(), true));
88
tabInfos.add(new TabInfo(MBeansTab.class, MBeansTab.getTabName(), true));
89
}
90
91
public static TabInfo[] getTabInfos() {
92
return tabInfos.toArray(new TabInfo[tabInfos.size()]);
93
}
94
95
VMPanel(ProxyClient proxyClient, int updateInterval) {
96
this.proxyClient = proxyClient;
97
this.updateInterval = updateInterval;
98
this.hostName = proxyClient.getHostName();
99
this.port = proxyClient.getPort();
100
this.userName = proxyClient.getUserName();
101
this.password = proxyClient.getPassword();
102
this.url = proxyClient.getUrl();
103
104
for (TabInfo tabInfo : tabInfos) {
105
if (tabInfo.tabVisible) {
106
addTab(tabInfo);
107
}
108
}
109
110
plugins = new LinkedHashMap<ExceptionSafePlugin, SwingWorker<?, ?>>();
111
for (JConsolePlugin p : JConsole.getPlugins()) {
112
p.setContext(proxyClient);
113
plugins.put(new ExceptionSafePlugin(p), null);
114
}
115
116
Utilities.updateTransparency(this);
117
118
ToolTipManager.sharedInstance().registerComponent(this);
119
120
// Start listening to connection state events
121
//
122
proxyClient.addPropertyChangeListener(this);
123
124
addMouseListener(new MouseAdapter() {
125
126
public void mouseClicked(MouseEvent e) {
127
if (connectedIconBounds != null && (e.getModifiers() & MouseEvent.BUTTON1_MASK) != 0 && connectedIconBounds.contains(e.getPoint())) {
128
129
if (isConnected()) {
130
userDisconnected = true;
131
disconnect();
132
wasConnected = false;
133
} else {
134
connect();
135
}
136
repaint();
137
}
138
}
139
});
140
141
}
142
private static Icon connectedIcon16 =
143
new ImageIcon(VMPanel.class.getResource("resources/connected16.png"));
144
private static Icon connectedIcon24 =
145
new ImageIcon(VMPanel.class.getResource("resources/connected24.png"));
146
private static Icon disconnectedIcon16 =
147
new ImageIcon(VMPanel.class.getResource("resources/disconnected16.png"));
148
private static Icon disconnectedIcon24 =
149
new ImageIcon(VMPanel.class.getResource("resources/disconnected24.png"));
150
private Rectangle connectedIconBounds;
151
152
// Override to increase right inset for tab area,
153
// in order to reserve space for the connect toggle.
154
public void setUI(TabbedPaneUI ui) {
155
Insets insets = (Insets) UIManager.getLookAndFeelDefaults().get("TabbedPane.tabAreaInsets");
156
if (insets != null) {
157
insets = (Insets) insets.clone();
158
insets.right += connectedIcon24.getIconWidth() + 8;
159
UIManager.put("TabbedPane.tabAreaInsets", insets);
160
}
161
super.setUI(ui);
162
}
163
164
// Override to paint the connect toggle
165
protected void paintComponent(Graphics g) {
166
super.paintComponent(g);
167
168
Icon icon;
169
Component c0 = getComponent(0);
170
if (c0 != null && c0.getY() > 24) {
171
icon = isConnected() ? connectedIcon24 : disconnectedIcon24;
172
} else {
173
icon = isConnected() ? connectedIcon16 : disconnectedIcon16;
174
}
175
Insets insets = getInsets();
176
int x = getWidth() - insets.right - icon.getIconWidth() - 4;
177
int y = insets.top;
178
if (c0 != null) {
179
y = (c0.getY() - icon.getIconHeight()) / 2;
180
}
181
icon.paintIcon(this, g, x, y);
182
connectedIconBounds = new Rectangle(x, y, icon.getIconWidth(), icon.getIconHeight());
183
}
184
185
public String getToolTipText(MouseEvent event) {
186
if (connectedIconBounds.contains(event.getPoint())) {
187
if (isConnected()) {
188
return Messages.CONNECTED_PUNCTUATION_CLICK_TO_DISCONNECT_;
189
} else {
190
return Messages.DISCONNECTED_PUNCTUATION_CLICK_TO_CONNECT_;
191
}
192
} else {
193
return super.getToolTipText(event);
194
}
195
}
196
197
private synchronized void addTab(TabInfo tabInfo) {
198
Tab tab = instantiate(tabInfo);
199
if (tab != null) {
200
addTab(tabInfo.name, tab);
201
} else {
202
tabInfo.tabVisible = false;
203
}
204
}
205
206
private synchronized void insertTab(TabInfo tabInfo, int index) {
207
Tab tab = instantiate(tabInfo);
208
if (tab != null) {
209
insertTab(tabInfo.name, null, tab, null, index);
210
} else {
211
tabInfo.tabVisible = false;
212
}
213
}
214
215
public synchronized void removeTabAt(int index) {
216
super.removeTabAt(index);
217
}
218
219
private Tab instantiate(TabInfo tabInfo) {
220
try {
221
Constructor<?> con = tabInfo.tabClass.getConstructor(VMPanel.class);
222
return (Tab) con.newInstance(this);
223
} catch (Exception ex) {
224
System.err.println(ex);
225
return null;
226
}
227
}
228
229
boolean isConnected() {
230
return proxyClient.isConnected();
231
}
232
233
public int getUpdateInterval() {
234
return updateInterval;
235
}
236
237
/**
238
* WARNING NEVER CALL THIS METHOD TO MAKE JMX REQUEST
239
* IF assertThread == false.
240
* DISPATCHER THREAD IS NOT ASSERTED.
241
* IT IS USED TO MAKE SOME LOCAL MANIPULATIONS.
242
*/
243
ProxyClient getProxyClient(boolean assertThread) {
244
if (assertThread) {
245
return getProxyClient();
246
} else {
247
return proxyClient;
248
}
249
}
250
251
public ProxyClient getProxyClient() {
252
String threadClass = Thread.currentThread().getClass().getName();
253
if (threadClass.equals("java.awt.EventDispatchThread")) {
254
String msg = "Calling VMPanel.getProxyClient() from the Event Dispatch Thread!";
255
new RuntimeException(msg).printStackTrace();
256
System.exit(1);
257
}
258
return proxyClient;
259
}
260
261
public void cleanUp() {
262
//proxyClient.disconnect();
263
for (Tab tab : getTabs()) {
264
tab.dispose();
265
}
266
for (JConsolePlugin p : plugins.keySet()) {
267
p.dispose();
268
}
269
// Cancel pending update tasks
270
//
271
if (timer != null) {
272
timer.cancel();
273
}
274
// Stop listening to connection state events
275
//
276
proxyClient.removePropertyChangeListener(this);
277
}
278
279
// Call on EDT
280
public void connect() {
281
if (isConnected()) {
282
// create plugin tabs if not done
283
createPluginTabs();
284
// Notify tabs
285
fireConnectedChange(true);
286
// Enable/disable tabs on initial update
287
initialUpdate = true;
288
// Start/Restart update timer on connect/reconnect
289
startUpdateTimer();
290
} else {
291
new Thread("VMPanel.connect") {
292
293
public void run() {
294
proxyClient.connect(shouldUseSSL);
295
}
296
}.start();
297
}
298
}
299
300
// Call on EDT
301
public void disconnect() {
302
proxyClient.disconnect();
303
updateFrameTitle();
304
}
305
306
// Called on EDT
307
public void propertyChange(PropertyChangeEvent ev) {
308
String prop = ev.getPropertyName();
309
310
if (prop == CONNECTION_STATE_PROPERTY) {
311
ConnectionState oldState = (ConnectionState) ev.getOldValue();
312
ConnectionState newState = (ConnectionState) ev.getNewValue();
313
switch (newState) {
314
case CONNECTING:
315
onConnecting();
316
break;
317
318
case CONNECTED:
319
if (progressBar != null) {
320
progressBar.setIndeterminate(false);
321
progressBar.setValue(100);
322
}
323
closeOptionPane();
324
updateFrameTitle();
325
// create tabs if not done
326
createPluginTabs();
327
repaint();
328
// Notify tabs
329
fireConnectedChange(true);
330
// Enable/disable tabs on initial update
331
initialUpdate = true;
332
// Start/Restart update timer on connect/reconnect
333
startUpdateTimer();
334
break;
335
336
case DISCONNECTED:
337
if (progressBar != null) {
338
progressBar.setIndeterminate(false);
339
progressBar.setValue(0);
340
closeOptionPane();
341
}
342
vmPanelDied();
343
if (oldState == ConnectionState.CONNECTED) {
344
// Notify tabs
345
fireConnectedChange(false);
346
}
347
break;
348
}
349
}
350
}
351
352
// Called on EDT
353
private void onConnecting() {
354
time0 = System.currentTimeMillis();
355
356
SwingUtilities.getWindowAncestor(this);
357
358
String connectionName = getConnectionName();
359
progressBar = new JProgressBar();
360
progressBar.setIndeterminate(true);
361
JPanel progressPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
362
progressPanel.add(progressBar);
363
364
Object[] message = {
365
"<html><h3>" + Resources.format(Messages.CONNECTING_TO1, connectionName) + "</h3></html>",
366
progressPanel,
367
"<html><b>" + Resources.format(Messages.CONNECTING_TO2, connectionName) + "</b></html>"
368
};
369
370
optionPane =
371
SheetDialog.showOptionDialog(this,
372
message,
373
JOptionPane.DEFAULT_OPTION,
374
JOptionPane.INFORMATION_MESSAGE, null,
375
new String[]{Messages.CANCEL},
376
0);
377
378
379
}
380
381
// Called on EDT
382
private void closeOptionPane() {
383
if (optionPane != null) {
384
new Thread("VMPanel.sleeper") {
385
public void run() {
386
long elapsed = System.currentTimeMillis() - time0;
387
if (elapsed < 2000) {
388
try {
389
sleep(2000 - elapsed);
390
} catch (InterruptedException ex) {
391
// Ignore
392
}
393
}
394
SwingUtilities.invokeLater(new Runnable() {
395
396
public void run() {
397
optionPane.setVisible(false);
398
progressBar = null;
399
}
400
});
401
}
402
}.start();
403
}
404
}
405
406
void updateFrameTitle() {
407
VMInternalFrame vmIF = getFrame();
408
if (vmIF != null) {
409
String displayName = getDisplayName();
410
if (!proxyClient.isConnected()) {
411
displayName = Resources.format(Messages.CONNECTION_NAME__DISCONNECTED_, displayName);
412
}
413
vmIF.setTitle(displayName);
414
}
415
}
416
417
private VMInternalFrame getFrame() {
418
if (vmIF == null) {
419
vmIF = (VMInternalFrame) SwingUtilities.getAncestorOfClass(VMInternalFrame.class,
420
this);
421
}
422
return vmIF;
423
}
424
425
// TODO: this method is not needed when all JConsole tabs
426
// are migrated to use the new JConsolePlugin API.
427
//
428
// A thread safe clone of all JConsole tabs
429
synchronized List<Tab> getTabs() {
430
ArrayList<Tab> list = new ArrayList<Tab>();
431
int n = getTabCount();
432
for (int i = 0; i < n; i++) {
433
Component c = getComponentAt(i);
434
if (c instanceof Tab) {
435
list.add((Tab) c);
436
}
437
}
438
return list;
439
}
440
441
private void startUpdateTimer() {
442
if (timer != null) {
443
timer.cancel();
444
}
445
TimerTask timerTask = new TimerTask() {
446
447
public void run() {
448
update();
449
}
450
};
451
String timerName = "Timer-" + getConnectionName();
452
timer = new Timer(timerName, true);
453
timer.schedule(timerTask, 0, updateInterval);
454
}
455
456
// Call on EDT
457
private void vmPanelDied() {
458
disconnect();
459
460
if (userDisconnected) {
461
userDisconnected = false;
462
return;
463
}
464
465
JOptionPane optionPane;
466
String msgTitle, msgExplanation, buttonStr;
467
468
if (wasConnected) {
469
wasConnected = false;
470
msgTitle = Messages.CONNECTION_LOST1;
471
msgExplanation = Resources.format(Messages.CONNECTING_TO2, getConnectionName());
472
buttonStr = Messages.RECONNECT;
473
} else if (shouldUseSSL) {
474
msgTitle = Messages.CONNECTION_FAILED_SSL1;
475
msgExplanation = Resources.format(Messages.CONNECTION_FAILED_SSL2, getConnectionName());
476
buttonStr = Messages.INSECURE;
477
} else {
478
msgTitle = Messages.CONNECTION_FAILED1;
479
msgExplanation = Resources.format(Messages.CONNECTION_FAILED2, getConnectionName());
480
buttonStr = Messages.CONNECT;
481
}
482
483
optionPane =
484
SheetDialog.showOptionDialog(this,
485
"<html><h3>" + msgTitle + "</h3>" +
486
"<b>" + msgExplanation + "</b>",
487
JOptionPane.DEFAULT_OPTION,
488
JOptionPane.WARNING_MESSAGE, null,
489
new String[]{buttonStr, Messages.CANCEL},
490
0);
491
492
optionPane.addPropertyChangeListener(new PropertyChangeListener() {
493
494
public void propertyChange(PropertyChangeEvent event) {
495
if (event.getPropertyName().equals(JOptionPane.VALUE_PROPERTY)) {
496
Object value = event.getNewValue();
497
498
if (value == Messages.RECONNECT || value == Messages.CONNECT) {
499
connect();
500
} else if (value == Messages.INSECURE) {
501
shouldUseSSL = false;
502
connect();
503
} else if (!everConnected) {
504
try {
505
getFrame().setClosed(true);
506
} catch (PropertyVetoException ex) {
507
// Should not happen, but can be ignored.
508
}
509
}
510
}
511
}
512
});
513
}
514
515
// Note: This method is called on a TimerTask thread. Any GUI manipulation
516
// must be performed with invokeLater() or invokeAndWait().
517
private Object lockObject = new Object();
518
519
private void update() {
520
synchronized (lockObject) {
521
if (!isConnected()) {
522
if (wasConnected) {
523
EventQueue.invokeLater(new Runnable() {
524
525
public void run() {
526
vmPanelDied();
527
}
528
});
529
}
530
wasConnected = false;
531
return;
532
} else {
533
wasConnected = true;
534
everConnected = true;
535
}
536
proxyClient.flush();
537
List<Tab> tabs = getTabs();
538
final int n = tabs.size();
539
for (int i = 0; i < n; i++) {
540
final int index = i;
541
try {
542
if (!proxyClient.isDead()) {
543
// Update tab
544
//
545
tabs.get(index).update();
546
// Enable tab on initial update
547
//
548
if (initialUpdate) {
549
EventQueue.invokeLater(new Runnable() {
550
551
public void run() {
552
setEnabledAt(index, true);
553
}
554
});
555
}
556
}
557
} catch (Exception e) {
558
// Disable tab on initial update
559
//
560
if (initialUpdate) {
561
EventQueue.invokeLater(new Runnable() {
562
public void run() {
563
setEnabledAt(index, false);
564
}
565
});
566
}
567
}
568
}
569
570
// plugin GUI update
571
for (ExceptionSafePlugin p : plugins.keySet()) {
572
SwingWorker<?, ?> sw = p.newSwingWorker();
573
SwingWorker<?, ?> prevSW = plugins.get(p);
574
// schedule SwingWorker to run only if the previous
575
// SwingWorker has finished its task and it hasn't started.
576
if (prevSW == null || prevSW.isDone()) {
577
if (sw == null || sw.getState() == SwingWorker.StateValue.PENDING) {
578
plugins.put(p, sw);
579
if (sw != null) {
580
p.executeSwingWorker(sw);
581
}
582
}
583
}
584
}
585
586
// Set the first enabled tab in the tab's list
587
// as the selected tab on initial update
588
//
589
if (initialUpdate) {
590
EventQueue.invokeLater(new Runnable() {
591
public void run() {
592
// Select first enabled tab if current tab isn't.
593
int index = getSelectedIndex();
594
if (index < 0 || !isEnabledAt(index)) {
595
for (int i = 0; i < n; i++) {
596
if (isEnabledAt(i)) {
597
setSelectedIndex(i);
598
break;
599
}
600
}
601
}
602
}
603
});
604
initialUpdate = false;
605
}
606
}
607
}
608
609
public String getHostName() {
610
return hostName;
611
}
612
613
public int getPort() {
614
return port;
615
}
616
617
public String getUserName() {
618
return userName;
619
}
620
621
public String getUrl() {
622
return url;
623
}
624
625
public String getPassword() {
626
return password;
627
}
628
629
public String getConnectionName() {
630
return proxyClient.connectionName();
631
}
632
633
public String getDisplayName() {
634
return proxyClient.getDisplayName();
635
}
636
637
static class TabInfo {
638
639
Class<? extends Tab> tabClass;
640
String name;
641
boolean tabVisible;
642
643
TabInfo(Class<? extends Tab> tabClass, String name, boolean tabVisible) {
644
this.tabClass = tabClass;
645
this.name = name;
646
this.tabVisible = tabVisible;
647
}
648
}
649
650
private void createPluginTabs() {
651
// add plugin tabs if not done
652
if (!pluginTabsAdded) {
653
for (JConsolePlugin p : plugins.keySet()) {
654
Map<String, JPanel> tabs = p.getTabs();
655
for (Map.Entry<String, JPanel> e : tabs.entrySet()) {
656
addTab(e.getKey(), e.getValue());
657
}
658
}
659
pluginTabsAdded = true;
660
}
661
}
662
663
private void fireConnectedChange(boolean connected) {
664
for (Tab tab : getTabs()) {
665
tab.firePropertyChange(JConsoleContext.CONNECTION_STATE_PROPERTY, !connected, connected);
666
}
667
}
668
}
669
670