PageRenderTime 63ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/src/share/classes/sun/tools/jconsole/JConsole.java

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