PageRenderTime 43ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/MRI-J/jdk/src/share/classes/sun/tools/jconsole/JConsole.java

http://github.com/GregBowyer/ManagedRuntimeInitiative
Java | 1112 lines | 877 code | 128 blank | 107 comment | 180 complexity | 488310b34434ebb7c89a5ed2a8590c0c MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, LGPL-3.0
  1. /*
  2. * Copyright 2004-2006 Sun Microsystems, Inc. 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. Sun designates this
  8. * particular file as subject to the "Classpath" exception as provided
  9. * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
  22. * CA 95054 USA or visit www.sun.com if you need additional information or
  23. * have any questions.
  24. */
  25. package sun.tools.jconsole;
  26. import java.awt.*;
  27. import java.awt.event.*;
  28. import java.beans.*;
  29. import java.io.*;
  30. import java.lang.reflect.InvocationTargetException;
  31. import java.net.*;
  32. import java.util.*;
  33. import java.util.List;
  34. import javax.swing.*;
  35. import javax.swing.border.*;
  36. import javax.swing.event.*;
  37. import javax.swing.plaf.*;
  38. import javax.management.remote.JMXServiceURL;
  39. import javax.management.remote.JMXConnector;
  40. import javax.security.auth.login.FailedLoginException;
  41. import javax.net.ssl.SSLHandshakeException;
  42. import com.sun.tools.jconsole.JConsolePlugin;
  43. import sun.net.util.IPAddressUtil;
  44. import static sun.tools.jconsole.Resources.*;
  45. import static sun.tools.jconsole.Utilities.*;
  46. @SuppressWarnings("serial")
  47. public class JConsole extends JFrame
  48. implements ActionListener, InternalFrameListener {
  49. static /*final*/ boolean IS_GTK;
  50. static /*final*/ boolean IS_WIN;
  51. static {
  52. // Apply the system L&F if it is GTK or Windows, and
  53. // the L&F is not specified using a system property.
  54. if (System.getProperty("swing.defaultlaf") == null) {
  55. String systemLaF = UIManager.getSystemLookAndFeelClassName();
  56. if (systemLaF.equals("com.sun.java.swing.plaf.gtk.GTKLookAndFeel") ||
  57. systemLaF.equals("com.sun.java.swing.plaf.windows.WindowsLookAndFeel")) {
  58. try {
  59. UIManager.setLookAndFeel(systemLaF);
  60. } catch (Exception e) {
  61. System.err.println(Resources.getText("JConsole: ", e.getMessage()));
  62. }
  63. }
  64. }
  65. updateLafValues();
  66. }
  67. static void updateLafValues() {
  68. String lafName = UIManager.getLookAndFeel().getClass().getName();
  69. IS_GTK = lafName.equals("com.sun.java.swing.plaf.gtk.GTKLookAndFeel");
  70. IS_WIN = lafName.equals("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
  71. //BorderedComponent.updateLafValues();
  72. }
  73. private final static String title =
  74. Resources.getText("Java Monitoring & Management Console");
  75. public final static String ROOT_URL =
  76. "service:jmx:";
  77. private static int updateInterval = 4000;
  78. private static String pluginPath = "";
  79. private JMenuBar menuBar;
  80. private JMenuItem hotspotMI, connectMI, exitMI;
  81. private WindowMenu windowMenu;
  82. private JMenuItem tileMI, cascadeMI, minimizeAllMI, restoreAllMI;
  83. private JMenuItem userGuideMI, aboutMI;
  84. private JButton connectButton;
  85. private JDesktopPane desktop;
  86. private ConnectDialog connectDialog;
  87. private CreateMBeanDialog createDialog;
  88. private ArrayList<VMInternalFrame> windows =
  89. new ArrayList<VMInternalFrame>();
  90. private int frameLoc = 5;
  91. static boolean debug;
  92. public JConsole(boolean hotspot) {
  93. super(title);
  94. setRootPane(new FixedJRootPane());
  95. setAccessibleDescription(this,
  96. getText("JConsole.accessibleDescription"));
  97. setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  98. menuBar = new JMenuBar();
  99. setJMenuBar(menuBar);
  100. // TODO: Use Actions !
  101. JMenu connectionMenu = new JMenu(getText("Connection"));
  102. connectionMenu.setMnemonic(getMnemonicInt("Connection"));
  103. menuBar.add(connectionMenu);
  104. if(hotspot) {
  105. hotspotMI = new JMenuItem(getText("Hotspot MBeans..."));
  106. hotspotMI.setMnemonic(getMnemonicInt("Hotspot MBeans..."));
  107. hotspotMI.setAccelerator(KeyStroke.
  108. getKeyStroke(KeyEvent.VK_H,
  109. InputEvent.CTRL_MASK));
  110. hotspotMI.addActionListener(this);
  111. connectionMenu.add(hotspotMI);
  112. connectionMenu.addSeparator();
  113. }
  114. connectMI = new JMenuItem(Resources.getText("New Connection..."));
  115. connectMI.setMnemonic(getMnemonicInt("New Connection..."));
  116. connectMI.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N,
  117. InputEvent.CTRL_MASK));
  118. connectMI.addActionListener(this);
  119. connectionMenu.add(connectMI);
  120. connectionMenu.addSeparator();
  121. exitMI = new JMenuItem(Resources.getText("Exit"));
  122. exitMI.setMnemonic(getMnemonicInt("Exit"));
  123. exitMI.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F4,
  124. InputEvent.ALT_MASK));
  125. exitMI.addActionListener(this);
  126. connectionMenu.add(exitMI);
  127. JMenu helpMenu = new JMenu(getText("HelpMenu.title"));
  128. helpMenu.setMnemonic(getMnemonicInt("HelpMenu.title"));
  129. menuBar.add(helpMenu);
  130. if (AboutDialog.isBrowseSupported()) {
  131. userGuideMI = new JMenuItem(getText("HelpMenu.UserGuide.title"));
  132. userGuideMI.setMnemonic(getMnemonicInt("HelpMenu.UserGuide.title"));
  133. userGuideMI.addActionListener(this);
  134. helpMenu.add(userGuideMI);
  135. helpMenu.addSeparator();
  136. }
  137. aboutMI = new JMenuItem(getText("HelpMenu.About.title"));
  138. aboutMI.setMnemonic(getMnemonicInt("HelpMenu.About.title"));
  139. aboutMI.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F1, 0));
  140. aboutMI.addActionListener(this);
  141. helpMenu.add(aboutMI);
  142. }
  143. public JDesktopPane getDesktopPane() {
  144. return desktop;
  145. }
  146. public List<VMInternalFrame> getInternalFrames() {
  147. return windows;
  148. }
  149. private void createMDI() {
  150. // Restore title - we now show connection name on internal frames
  151. setTitle(title);
  152. Container cp = getContentPane();
  153. Component oldCenter =
  154. ((BorderLayout)cp.getLayout()).
  155. getLayoutComponent(BorderLayout.CENTER);
  156. windowMenu = new WindowMenu(Resources.getText("Window"));
  157. windowMenu.setMnemonic(getMnemonicInt("Window"));
  158. // Add Window menu before Help menu
  159. menuBar.add(windowMenu, menuBar.getComponentCount() - 1);
  160. desktop = new JDesktopPane();
  161. desktop.setBackground(new Color(235, 245, 255));
  162. cp.add(desktop, BorderLayout.CENTER);
  163. if (oldCenter instanceof VMPanel) {
  164. addFrame((VMPanel)oldCenter);
  165. }
  166. }
  167. private class WindowMenu extends JMenu {
  168. VMInternalFrame[] windowMenuWindows = new VMInternalFrame[0];
  169. int separatorPosition;
  170. // The width value of viewR is used to truncate long menu items.
  171. // The rest are placeholders and are ignored for this purpose.
  172. Rectangle viewR = new Rectangle(0, 0, 400, 20);
  173. Rectangle textR = new Rectangle(0, 0, 0, 0);
  174. Rectangle iconR = new Rectangle(0, 0, 0, 0);
  175. WindowMenu(String text) {
  176. super(text);
  177. cascadeMI = new JMenuItem(Resources.getText("Cascade"));
  178. cascadeMI.setMnemonic(getMnemonicInt("Cascade"));
  179. cascadeMI.addActionListener(JConsole.this);
  180. add(cascadeMI);
  181. tileMI = new JMenuItem(Resources.getText("Tile"));
  182. tileMI.setMnemonic(getMnemonicInt("Tile"));
  183. tileMI.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_T,
  184. InputEvent.CTRL_MASK));
  185. tileMI.addActionListener(JConsole.this);
  186. add(tileMI);
  187. minimizeAllMI = new JMenuItem(Resources.getText("Minimize All"));
  188. minimizeAllMI.setMnemonic(getMnemonicInt("Minimize All"));
  189. minimizeAllMI.addActionListener(JConsole.this);
  190. add(minimizeAllMI);
  191. restoreAllMI = new JMenuItem(Resources.getText("Restore All"));
  192. restoreAllMI.setMnemonic(getMnemonicInt("Restore All"));
  193. restoreAllMI.addActionListener(JConsole.this);
  194. add(restoreAllMI);
  195. separatorPosition = getMenuComponentCount();
  196. }
  197. private void add(VMInternalFrame vmIF) {
  198. if (separatorPosition == getMenuComponentCount()) {
  199. addSeparator();
  200. }
  201. int index = -1;
  202. int position = separatorPosition + 1;
  203. int n = windowMenuWindows.length;
  204. for (int i = 0; i < n; i++) {
  205. if (windowMenuWindows[i] != null) {
  206. // Slot is in use, try next
  207. position++;
  208. } else {
  209. // Found a free slot
  210. index = i;
  211. break;
  212. }
  213. }
  214. if (index == -1) {
  215. // Create a slot at the end
  216. VMInternalFrame[] newArray = new VMInternalFrame[n + 1];
  217. System.arraycopy(windowMenuWindows, 0, newArray, 0, n);
  218. windowMenuWindows = newArray;
  219. index = n;
  220. }
  221. windowMenuWindows[index] = vmIF;
  222. String indexString = "" + (index+1);
  223. String vmName = vmIF.getVMPanel().getDisplayName();
  224. // Maybe truncate menu item string and end with "..."
  225. String text =
  226. SwingUtilities.layoutCompoundLabel(this,
  227. getGraphics().getFontMetrics(getFont()),
  228. indexString + " " + vmName,
  229. null, 0, 0, 0, 0,
  230. viewR, iconR, textR, 0);
  231. JMenuItem mi = new JMenuItem(text);
  232. if (text.endsWith("...")) {
  233. mi.setToolTipText(vmName);
  234. }
  235. // Set mnemonic using last digit of number
  236. int nDigits = indexString.length();
  237. mi.setMnemonic(indexString.charAt(nDigits-1));
  238. mi.setDisplayedMnemonicIndex(nDigits-1);
  239. mi.putClientProperty("JConsole.vmIF", vmIF);
  240. mi.addActionListener(JConsole.this);
  241. vmIF.putClientProperty("JConsole.menuItem", mi);
  242. add(mi, position);
  243. }
  244. private void remove(VMInternalFrame vmIF) {
  245. for (int i = 0; i < windowMenuWindows.length; i++) {
  246. if (windowMenuWindows[i] == vmIF) {
  247. windowMenuWindows[i] = null;
  248. }
  249. }
  250. JMenuItem mi = (JMenuItem)vmIF.getClientProperty("JConsole.menuItem");
  251. remove(mi);
  252. mi.putClientProperty("JConsole.vmIF", null);
  253. vmIF.putClientProperty("JConsole.menuItem", null);
  254. if (separatorPosition == getMenuComponentCount() - 1) {
  255. remove(getMenuComponent(getMenuComponentCount() - 1));
  256. }
  257. }
  258. }
  259. public void actionPerformed(ActionEvent ev) {
  260. Object src = ev.getSource();
  261. if (src == hotspotMI) {
  262. showCreateMBeanDialog();
  263. }
  264. if (src == connectButton || src == connectMI) {
  265. VMPanel vmPanel = null;
  266. JInternalFrame vmIF = desktop.getSelectedFrame();
  267. if (vmIF instanceof VMInternalFrame) {
  268. vmPanel = ((VMInternalFrame)vmIF).getVMPanel();
  269. }
  270. String hostName = "";
  271. String url = "";
  272. if (vmPanel != null) {
  273. hostName = vmPanel.getHostName();
  274. if(vmPanel.getUrl() != null)
  275. url = vmPanel.getUrl();
  276. }
  277. showConnectDialog(url, hostName, 0, null, null, null);
  278. } else if (src == tileMI) {
  279. tileWindows();
  280. } else if (src == cascadeMI) {
  281. cascadeWindows();
  282. } else if (src == minimizeAllMI) {
  283. for (VMInternalFrame vmIF : windows) {
  284. try {
  285. vmIF.setIcon(true);
  286. } catch (PropertyVetoException ex) {
  287. // Ignore
  288. }
  289. }
  290. } else if (src == restoreAllMI) {
  291. for (VMInternalFrame vmIF : windows) {
  292. try {
  293. vmIF.setIcon(false);
  294. } catch (PropertyVetoException ex) {
  295. // Ignore
  296. }
  297. }
  298. } else if (src == exitMI) {
  299. System.exit(0);
  300. } else if (src == userGuideMI) {
  301. AboutDialog.browseUserGuide(this);
  302. } else if (src == aboutMI) {
  303. AboutDialog.showAboutDialog(this);
  304. } else if (src instanceof JMenuItem) {
  305. JMenuItem mi = (JMenuItem)src;
  306. VMInternalFrame vmIF = (VMInternalFrame)mi.
  307. getClientProperty("JConsole.vmIF");
  308. if (vmIF != null) {
  309. try {
  310. vmIF.setIcon(false);
  311. vmIF.setSelected(true);
  312. } catch (PropertyVetoException ex) {
  313. // Ignore
  314. }
  315. vmIF.moveToFront();
  316. }
  317. }
  318. }
  319. public void tileWindows() {
  320. int w = -1;
  321. int h = -1;
  322. int n = 0;
  323. for (VMInternalFrame vmIF : windows) {
  324. if (!vmIF.isIcon()) {
  325. n++;
  326. if (w == -1) {
  327. try {
  328. vmIF.setMaximum(true);
  329. w = vmIF.getWidth();
  330. h = vmIF.getHeight();
  331. } catch (PropertyVetoException ex) {
  332. // Ignore
  333. }
  334. }
  335. }
  336. }
  337. if (n > 0 && w > 0 && h > 0) {
  338. int rows = (int)Math.ceil(Math.sqrt(n));
  339. int cols = n / rows;
  340. if (rows * cols < n) cols++;
  341. int x = 0;
  342. int y = 0;
  343. w /= cols;
  344. h /= rows;
  345. int col = 0;
  346. for (VMInternalFrame vmIF : windows) {
  347. if (!vmIF.isIcon()) {
  348. try {
  349. vmIF.setMaximum(n==1);
  350. } catch (PropertyVetoException ex) {
  351. // Ignore
  352. }
  353. if (n > 1) {
  354. vmIF.setBounds(x, y, w, h);
  355. }
  356. if (col < cols-1) {
  357. col++;
  358. x += w;
  359. } else {
  360. col = 0;
  361. x = 0;
  362. y += h;
  363. }
  364. }
  365. }
  366. }
  367. }
  368. public void cascadeWindows() {
  369. int n = 0;
  370. int w = -1;
  371. int h = -1;
  372. for (VMInternalFrame vmIF : windows) {
  373. if (!vmIF.isIcon()) {
  374. try {
  375. vmIF.setMaximum(false);
  376. } catch (PropertyVetoException ex) {
  377. // Ignore
  378. }
  379. n++;
  380. vmIF.pack();
  381. if (w == -1) {
  382. try {
  383. w = vmIF.getWidth();
  384. h = vmIF.getHeight();
  385. vmIF.setMaximum(true);
  386. w = vmIF.getWidth() - w;
  387. h = vmIF.getHeight() - h;
  388. vmIF.pack();
  389. } catch (PropertyVetoException ex) {
  390. // Ignore
  391. }
  392. }
  393. }
  394. }
  395. int x = 0;
  396. int y = 0;
  397. int dX = (n > 1) ? (w / (n - 1)) : 0;
  398. int dY = (n > 1) ? (h / (n - 1)) : 0;
  399. for (VMInternalFrame vmIF : windows) {
  400. if (!vmIF.isIcon()) {
  401. vmIF.setLocation(x, y);
  402. vmIF.moveToFront();
  403. x += dX;
  404. y += dY;
  405. }
  406. }
  407. }
  408. // Call on EDT
  409. void addHost(String hostName, int port,
  410. String userName, String password) {
  411. addHost(hostName, port, userName, password, false);
  412. }
  413. // Call on EDT
  414. void addVmid(LocalVirtualMachine lvm) {
  415. addVmid(lvm, false);
  416. }
  417. // Call on EDT
  418. void addVmid(final LocalVirtualMachine lvm, final boolean tile) {
  419. new Thread("JConsole.addVmid") {
  420. public void run() {
  421. try {
  422. addProxyClient(ProxyClient.getProxyClient(lvm), tile);
  423. } catch (final SecurityException ex) {
  424. failed(ex, null, null, null);
  425. } catch (final IOException ex) {
  426. failed(ex, null, null, null);
  427. }
  428. }
  429. }.start();
  430. }
  431. // Call on EDT
  432. void addUrl(final String url,
  433. final String userName,
  434. final String password,
  435. final boolean tile) {
  436. new Thread("JConsole.addUrl") {
  437. public void run() {
  438. try {
  439. addProxyClient(ProxyClient.getProxyClient(url, userName, password),
  440. tile);
  441. } catch (final MalformedURLException ex) {
  442. failed(ex, url, userName, password);
  443. } catch (final SecurityException ex) {
  444. failed(ex, url, userName, password);
  445. } catch (final IOException ex) {
  446. failed(ex, url, userName, password);
  447. }
  448. }
  449. }.start();
  450. }
  451. // Call on EDT
  452. void addHost(final String hostName, final int port,
  453. final String userName, final String password,
  454. final boolean tile) {
  455. new Thread("JConsole.addHost") {
  456. public void run() {
  457. try {
  458. addProxyClient(ProxyClient.getProxyClient(hostName, port,
  459. userName, password),
  460. tile);
  461. } catch (final IOException ex) {
  462. dbgStackTrace(ex);
  463. SwingUtilities.invokeLater(new Runnable() {
  464. public void run() {
  465. showConnectDialog(null, hostName, port,
  466. userName, password, errorMessage(ex));
  467. }
  468. });
  469. }
  470. }
  471. }.start();
  472. }
  473. // Call on worker thread
  474. void addProxyClient(final ProxyClient proxyClient, final boolean tile) {
  475. SwingUtilities.invokeLater(new Runnable() {
  476. public void run() {
  477. VMPanel vmPanel = new VMPanel(proxyClient, updateInterval);
  478. addFrame(vmPanel);
  479. if (tile) {
  480. SwingUtilities.invokeLater(new Runnable() {
  481. public void run() {
  482. tileWindows();
  483. }
  484. });
  485. }
  486. vmPanel.connect();
  487. }
  488. });
  489. }
  490. // Call on worker thread
  491. private void failed(final Exception ex,
  492. final String url,
  493. final String userName,
  494. final String password) {
  495. SwingUtilities.invokeLater(new Runnable() {
  496. public void run() {
  497. dbgStackTrace(ex);
  498. showConnectDialog(url,
  499. null,
  500. -1,
  501. userName,
  502. password,
  503. errorMessage(ex));
  504. }
  505. });
  506. }
  507. private VMInternalFrame addFrame(VMPanel vmPanel) {
  508. final VMInternalFrame vmIF = new VMInternalFrame(vmPanel);
  509. for (VMInternalFrame f : windows) {
  510. try {
  511. f.setMaximum(false);
  512. } catch (PropertyVetoException ex) {
  513. // Ignore
  514. }
  515. }
  516. desktop.add(vmIF);
  517. vmIF.setLocation(frameLoc, frameLoc);
  518. frameLoc += 30;
  519. vmIF.setVisible(true);
  520. windows.add(vmIF);
  521. if (windows.size() == 1) {
  522. try {
  523. vmIF.setMaximum(true);
  524. } catch (PropertyVetoException ex) {
  525. // Ignore
  526. }
  527. }
  528. vmIF.addInternalFrameListener(this);
  529. windowMenu.add(vmIF);
  530. return vmIF;
  531. }
  532. private void showConnectDialog(String url,
  533. String hostName,
  534. int port,
  535. String userName,
  536. String password,
  537. String msg) {
  538. if (connectDialog == null) {
  539. connectDialog = new ConnectDialog(this);
  540. }
  541. connectDialog.setConnectionParameters(url,
  542. hostName,
  543. port,
  544. userName,
  545. password,
  546. msg);
  547. connectDialog.refresh();
  548. connectDialog.setVisible(true);
  549. try {
  550. // Bring to front of other dialogs
  551. connectDialog.setSelected(true);
  552. } catch (PropertyVetoException e) {
  553. }
  554. }
  555. private void showCreateMBeanDialog() {
  556. if (createDialog == null) {
  557. createDialog = new CreateMBeanDialog(this);
  558. }
  559. createDialog.setVisible(true);
  560. try {
  561. // Bring to front of other dialogs
  562. createDialog.setSelected(true);
  563. } catch (PropertyVetoException e) {
  564. }
  565. }
  566. private void removeVMInternalFrame(VMInternalFrame vmIF) {
  567. windowMenu.remove(vmIF);
  568. desktop.remove(vmIF);
  569. desktop.repaint();
  570. vmIF.getVMPanel().cleanUp();
  571. vmIF.dispose();
  572. }
  573. private boolean isProxyClientUsed(ProxyClient client) {
  574. for(VMInternalFrame frame : windows) {
  575. ProxyClient cli = frame.getVMPanel().getProxyClient(false);
  576. if(client == cli)
  577. return true;
  578. }
  579. return false;
  580. }
  581. static boolean isValidRemoteString(String txt) {
  582. boolean valid = false;
  583. if (txt != null) {
  584. txt = txt.trim();
  585. if (txt.startsWith(ROOT_URL)) {
  586. if (txt.length() > ROOT_URL.length()) {
  587. valid = true;
  588. }
  589. } else {
  590. //---------------------------------------
  591. // Supported host and port combinations:
  592. // hostname:port
  593. // IPv4Address:port
  594. // [IPv6Address]:port
  595. //---------------------------------------
  596. // Is literal IPv6 address?
  597. //
  598. if (txt.startsWith("[")) {
  599. int index = txt.indexOf("]:");
  600. if (index != -1) {
  601. // Extract literal IPv6 address
  602. //
  603. String address = txt.substring(1, index);
  604. if (IPAddressUtil.isIPv6LiteralAddress(address)) {
  605. // Extract port
  606. //
  607. try {
  608. String portStr = txt.substring(index + 2);
  609. int port = Integer.parseInt(portStr);
  610. if (port >= 0 && port <= 0xFFFF) {
  611. valid = true;
  612. }
  613. } catch (NumberFormatException ex) {
  614. valid = false;
  615. }
  616. }
  617. }
  618. } else {
  619. String[] s = txt.split(":");
  620. if (s.length == 2) {
  621. try {
  622. int port = Integer.parseInt(s[1]);
  623. if (port >= 0 && port <= 0xFFFF) {
  624. valid = true;
  625. }
  626. } catch (NumberFormatException ex) {
  627. valid = false;
  628. }
  629. }
  630. }
  631. }
  632. }
  633. return valid;
  634. }
  635. private String errorMessage(Exception ex) {
  636. String msg = Resources.getText("Connection failed");
  637. if (ex instanceof IOException || ex instanceof SecurityException) {
  638. Throwable cause = null;
  639. Throwable c = ex.getCause();
  640. while (c != null) {
  641. cause = c;
  642. c = c.getCause();
  643. }
  644. if (cause instanceof ConnectException) {
  645. return msg + ": " + cause.getMessage();
  646. } else if (cause instanceof UnknownHostException) {
  647. return Resources.getText("Unknown Host", cause.getMessage());
  648. } else if (cause instanceof NoRouteToHostException) {
  649. return msg + ": " + cause.getMessage();
  650. } else if (cause instanceof FailedLoginException) {
  651. return msg + ": " + cause.getMessage();
  652. } else if (cause instanceof SSLHandshakeException) {
  653. return msg + ": "+ cause.getMessage();
  654. }
  655. } else if (ex instanceof MalformedURLException) {
  656. return Resources.getText("Invalid URL", ex.getMessage());
  657. }
  658. return msg + ": " + ex.getMessage();
  659. }
  660. // InternalFrameListener interface
  661. public void internalFrameClosing(InternalFrameEvent e) {
  662. VMInternalFrame vmIF = (VMInternalFrame)e.getInternalFrame();
  663. removeVMInternalFrame(vmIF);
  664. windows.remove(vmIF);
  665. ProxyClient client = vmIF.getVMPanel().getProxyClient(false);
  666. if(!isProxyClientUsed(client))
  667. client.markAsDead();
  668. if (windows.size() == 0) {
  669. showConnectDialog("", "", 0, null, null, null);
  670. }
  671. }
  672. public void internalFrameOpened(InternalFrameEvent e) {}
  673. public void internalFrameClosed(InternalFrameEvent e) {}
  674. public void internalFrameIconified(InternalFrameEvent e) {}
  675. public void internalFrameDeiconified(InternalFrameEvent e) {}
  676. public void internalFrameActivated(InternalFrameEvent e) {}
  677. public void internalFrameDeactivated(InternalFrameEvent e) {}
  678. private static void usage() {
  679. System.err.println(Resources.getText("zz usage text", "jconsole"));
  680. }
  681. private static void mainInit(final List<String> urls,
  682. final List<String> hostNames,
  683. final List<Integer> ports,
  684. final List<LocalVirtualMachine> vmids,
  685. final ProxyClient proxyClient,
  686. final boolean noTile,
  687. final boolean hotspot) {
  688. // Always create Swing GUI on the Event Dispatching Thread
  689. SwingUtilities.invokeLater(new Runnable() {
  690. public void run() {
  691. JConsole jConsole = new JConsole(hotspot);
  692. // Center the window on screen, taking into account screen
  693. // size and insets.
  694. Toolkit toolkit = Toolkit.getDefaultToolkit();
  695. GraphicsConfiguration gc = jConsole.getGraphicsConfiguration();
  696. Dimension scrSize = toolkit.getScreenSize();
  697. Insets scrInsets = toolkit.getScreenInsets(gc);
  698. Rectangle scrBounds =
  699. new Rectangle(scrInsets.left, scrInsets.top,
  700. scrSize.width - scrInsets.left - scrInsets.right,
  701. scrSize.height - scrInsets.top - scrInsets.bottom);
  702. int w = Math.min(900, scrBounds.width);
  703. int h = Math.min(750, scrBounds.height);
  704. jConsole.setBounds(scrBounds.x + (scrBounds.width - w) / 2,
  705. scrBounds.y + (scrBounds.height - h) / 2,
  706. w, h);
  707. jConsole.setVisible(true);
  708. jConsole.createMDI();
  709. for (int i = 0; i < hostNames.size(); i++) {
  710. jConsole.addHost(hostNames.get(i), ports.get(i),
  711. null, null,
  712. (i == hostNames.size() - 1) ?
  713. !noTile : false);
  714. }
  715. for (int i = 0; i < urls.size(); i++) {
  716. jConsole.addUrl(urls.get(i),
  717. null,
  718. null,
  719. (i == urls.size() - 1) ?
  720. !noTile : false);
  721. }
  722. for (int i = 0; i < vmids.size(); i++) {
  723. jConsole.addVmid(vmids.get(i),
  724. (i == vmids.size() - 1) ?
  725. !noTile : false);
  726. }
  727. if (vmids.size() == 0 &&
  728. hostNames.size() == 0 &&
  729. urls.size() == 0) {
  730. jConsole.showConnectDialog(null,
  731. null,
  732. 0,
  733. null,
  734. null,
  735. null);
  736. }
  737. }
  738. });
  739. }
  740. public static void main(String[] args) {
  741. boolean noTile = false, hotspot = false;
  742. int argIndex = 0;
  743. ProxyClient proxyClient = null;
  744. if (System.getProperty("jconsole.showOutputViewer") != null) {
  745. OutputViewer.init();
  746. }
  747. while (args.length - argIndex > 0 && args[argIndex].startsWith("-")) {
  748. String arg = args[argIndex++];
  749. if (arg.equals("-h") ||
  750. arg.equals("-help") ||
  751. arg.equals("-?")) {
  752. usage();
  753. return;
  754. } else if (arg.startsWith("-interval=")) {
  755. try {
  756. updateInterval = Integer.parseInt(arg.substring(10)) *
  757. 1000;
  758. } catch (NumberFormatException ex) {
  759. usage();
  760. return;
  761. }
  762. } else if (arg.equals("-pluginpath")) {
  763. if (argIndex < args.length && !args[argIndex].startsWith("-")) {
  764. pluginPath = args[argIndex++];
  765. } else {
  766. // Invalid argument
  767. usage();
  768. return;
  769. }
  770. } else if (arg.equals("-notile")) {
  771. noTile = true;
  772. } else if (arg.equals("-version")) {
  773. Version.print(System.err);
  774. return;
  775. } else if (arg.equals("-debug")) {
  776. debug = true;
  777. } else if (arg.equals("-fullversion")) {
  778. Version.printFullVersion(System.err);
  779. return;
  780. } else {
  781. // Unknown switch
  782. usage();
  783. return;
  784. }
  785. }
  786. if (System.getProperty("jconsole.showUnsupported") != null) {
  787. hotspot = true;
  788. }
  789. List<String> urls = new ArrayList<String>();
  790. List<String> hostNames = new ArrayList<String>();
  791. List<Integer> ports = new ArrayList<Integer>();
  792. List<LocalVirtualMachine> vms = new ArrayList<LocalVirtualMachine>();
  793. for (int i = argIndex; i < args.length; i++) {
  794. String arg = args[i];
  795. if (isValidRemoteString(arg)) {
  796. if (arg.startsWith(ROOT_URL)) {
  797. urls.add(arg);
  798. } else if (arg.matches(".*:[0-9]*")) {
  799. int p = arg.lastIndexOf(':');
  800. hostNames.add(arg.substring(0, p));
  801. try {
  802. ports.add(Integer.parseInt(arg.substring(p+1)));
  803. } catch (NumberFormatException ex) {
  804. usage();
  805. return;
  806. }
  807. }
  808. } else {
  809. if (!isLocalAttachAvailable()) {
  810. System.err.println("Local process monitoring is not supported");
  811. return;
  812. }
  813. try {
  814. int vmid = Integer.parseInt(arg);
  815. LocalVirtualMachine lvm =
  816. LocalVirtualMachine.getLocalVirtualMachine(vmid);
  817. if (lvm == null) {
  818. System.err.println("Invalid process id:" + vmid);
  819. return;
  820. }
  821. vms.add(lvm);
  822. } catch (NumberFormatException ex) {
  823. usage();
  824. return;
  825. }
  826. }
  827. }
  828. mainInit(urls, hostNames, ports, vms, proxyClient, noTile, hotspot);
  829. }
  830. public static boolean isDebug() {
  831. return debug;
  832. }
  833. private static void dbgStackTrace(Exception ex) {
  834. if (debug) {
  835. ex.printStackTrace();
  836. }
  837. }
  838. private static final boolean localAttachmentSupported;
  839. static {
  840. boolean supported;
  841. try {
  842. Class.forName("com.sun.tools.attach.VirtualMachine");
  843. Class.forName("sun.management.ConnectorAddressLink");
  844. supported = true;
  845. } catch (NoClassDefFoundError x) {
  846. supported = false;
  847. } catch (ClassNotFoundException x) {
  848. supported = false;
  849. }
  850. localAttachmentSupported = supported;
  851. }
  852. public static boolean isLocalAttachAvailable() {
  853. return localAttachmentSupported;
  854. }
  855. private static ServiceLoader<JConsolePlugin> pluginService = null;
  856. // Return a list of newly instantiated JConsolePlugin objects
  857. static synchronized List<JConsolePlugin> getPlugins() {
  858. if (pluginService == null) {
  859. // First time loading and initializing the plugins
  860. initPluginService(pluginPath);
  861. } else {
  862. // reload the plugin so that new instances will be created
  863. pluginService.reload();
  864. }
  865. List<JConsolePlugin> plugins = new ArrayList<JConsolePlugin>();
  866. for (JConsolePlugin p : pluginService) {
  867. plugins.add(p);
  868. }
  869. return plugins;
  870. }
  871. private static void initPluginService(String pluginPath) {
  872. if (pluginPath.length() > 0) {
  873. try {
  874. ClassLoader pluginCL = new URLClassLoader(pathToURLs(pluginPath));
  875. ServiceLoader<JConsolePlugin> plugins =
  876. ServiceLoader.load(JConsolePlugin.class, pluginCL);
  877. // validate all plugins
  878. for (JConsolePlugin p : plugins) {
  879. if (isDebug()) {
  880. System.out.println("Plugin " + p.getClass() + " loaded.");
  881. }
  882. }
  883. pluginService = plugins;
  884. } catch (ServiceConfigurationError e) {
  885. // Error occurs during initialization of plugin
  886. System.out.println(Resources.getText("Fail to load plugin",
  887. e.getMessage()));
  888. } catch (MalformedURLException e) {
  889. if (JConsole.isDebug()) {
  890. e.printStackTrace();
  891. }
  892. System.out.println(Resources.getText("Invalid plugin path",
  893. e.getMessage()));
  894. }
  895. }
  896. if (pluginService == null) {
  897. initEmptyPlugin();
  898. }
  899. }
  900. private static void initEmptyPlugin() {
  901. ClassLoader pluginCL = new URLClassLoader(new URL[0]);
  902. pluginService = ServiceLoader.load(JConsolePlugin.class, pluginCL);
  903. }
  904. /**
  905. * Utility method for converting a search path string to an array
  906. * of directory and JAR file URLs.
  907. *
  908. * @param path the search path string
  909. * @return the resulting array of directory and JAR file URLs
  910. */
  911. private static URL[] pathToURLs(String path) throws MalformedURLException {
  912. String[] names = path.split(File.pathSeparator);
  913. URL[] urls = new URL[names.length];
  914. int count = 0;
  915. for (String f : names) {
  916. URL url = fileToURL(new File(f));
  917. urls[count++] = url;
  918. }
  919. return urls;
  920. }
  921. /**
  922. * Returns the directory or JAR file URL corresponding to the specified
  923. * local file name.
  924. *
  925. * @param file the File object
  926. * @return the resulting directory or JAR file URL, or null if unknown
  927. */
  928. private static URL fileToURL(File file) throws MalformedURLException {
  929. String name;
  930. try {
  931. name = file.getCanonicalPath();
  932. } catch (IOException e) {
  933. name = file.getAbsolutePath();
  934. }
  935. name = name.replace(File.separatorChar, '/');
  936. if (!name.startsWith("/")) {
  937. name = "/" + name;
  938. }
  939. // If the file does not exist, then assume that it's a directory
  940. if (!file.isFile()) {
  941. name = name + "/";
  942. }
  943. return new URL("file", "", name);
  944. }
  945. private static class FixedJRootPane extends JRootPane {
  946. public void updateUI() {
  947. updateLafValues();
  948. super.updateUI();
  949. }
  950. /**
  951. * The revalidate method seems to be the only one that gets
  952. * called whenever there is a change of L&F or change of theme
  953. * in Windows L&F and GTK L&F.
  954. */
  955. @Override
  956. public void revalidate() {
  957. // Workaround for Swing bug where the titledborder in both
  958. // GTK and Windows L&F's use calculated colors instead of
  959. // the highlight/shadow colors from the theme.
  960. //
  961. // Putting null removes any previous override and causes a
  962. // fallback to the current L&F's value.
  963. UIManager.put("TitledBorder.border", null);
  964. Border border = UIManager.getBorder("TitledBorder.border");
  965. if (border instanceof BorderUIResource.EtchedBorderUIResource) {
  966. Color highlight = UIManager.getColor("ToolBar.highlight");
  967. Color shadow = UIManager.getColor("ToolBar.shadow");
  968. border = new BorderUIResource.EtchedBorderUIResource(highlight,
  969. shadow);
  970. UIManager.put("TitledBorder.border", border);
  971. }
  972. if (IS_GTK) {
  973. // Workaround for Swing bug where the titledborder in
  974. // GTK L&F use hardcoded color and font for the title
  975. // instead of getting them from the theme.
  976. UIManager.put("TitledBorder.titleColor",
  977. UIManager.getColor("Label.foreground"));
  978. UIManager.put("TitledBorder.font",
  979. UIManager.getFont("Label.font"));
  980. }
  981. super.revalidate();
  982. }
  983. }
  984. }