--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.jconsole/share/classes/sun/tools/jconsole/JConsole.java Tue Sep 12 19:03:39 2017 +0200
@@ -0,0 +1,1101 @@
+/*
+ * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.tools.jconsole;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.beans.*;
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import java.util.List;
+
+import javax.swing.*;
+import javax.swing.border.*;
+import javax.swing.event.*;
+import javax.swing.plaf.*;
+import javax.security.auth.login.FailedLoginException;
+import javax.net.ssl.SSLHandshakeException;
+
+import com.sun.tools.jconsole.JConsolePlugin;
+
+import sun.net.util.IPAddressUtil;
+
+import static sun.tools.jconsole.Utilities.*;
+
+@SuppressWarnings("serial")
+public class JConsole extends JFrame
+ implements ActionListener, InternalFrameListener {
+
+ static /*final*/ boolean IS_GTK;
+ static /*final*/ boolean IS_WIN;
+
+ static {
+ // Apply the system L&F if it is GTK or Windows, and
+ // the L&F is not specified using a system property.
+ if (System.getProperty("swing.defaultlaf") == null) {
+ String systemLaF = UIManager.getSystemLookAndFeelClassName();
+ if (systemLaF.equals("com.sun.java.swing.plaf.gtk.GTKLookAndFeel") ||
+ systemLaF.equals("com.sun.java.swing.plaf.windows.WindowsLookAndFeel")) {
+
+ try {
+ UIManager.setLookAndFeel(systemLaF);
+ } catch (Exception e) {
+ System.err.println(Resources.format(Messages.JCONSOLE_COLON_, e.getMessage()));
+ }
+ }
+ }
+
+ updateLafValues();
+ }
+
+
+ static void updateLafValues() {
+ String lafName = UIManager.getLookAndFeel().getClass().getName();
+ IS_GTK = lafName.equals("com.sun.java.swing.plaf.gtk.GTKLookAndFeel");
+ IS_WIN = lafName.equals("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
+
+ //BorderedComponent.updateLafValues();
+ }
+
+
+ private final static String title =
+ Messages.JAVA_MONITORING___MANAGEMENT_CONSOLE;
+ public final static String ROOT_URL =
+ "service:jmx:";
+
+ private static int updateInterval = 4000;
+ private static String pluginPath = "";
+
+ private JMenuBar menuBar;
+ private JMenuItem hotspotMI, connectMI, exitMI;
+ private WindowMenu windowMenu;
+ private JMenuItem tileMI, cascadeMI, minimizeAllMI, restoreAllMI;
+ private JMenuItem userGuideMI, aboutMI;
+
+ private JButton connectButton;
+ private JDesktopPane desktop;
+ private ConnectDialog connectDialog;
+ private CreateMBeanDialog createDialog;
+
+ private ArrayList<VMInternalFrame> windows =
+ new ArrayList<VMInternalFrame>();
+
+ private int frameLoc = 5;
+ static boolean debug;
+
+ public JConsole(boolean hotspot) {
+ super(title);
+
+ setRootPane(new FixedJRootPane());
+ setAccessibleDescription(this,
+ Messages.JCONSOLE_ACCESSIBLE_DESCRIPTION);
+ setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+
+ menuBar = new JMenuBar();
+ setJMenuBar(menuBar);
+
+ // TODO: Use Actions !
+
+ JMenu connectionMenu = new JMenu(Messages.CONNECTION);
+ connectionMenu.setMnemonic(Resources.getMnemonicInt(Messages.CONNECTION));
+ menuBar.add(connectionMenu);
+ if(hotspot) {
+ hotspotMI = new JMenuItem(Messages.HOTSPOT_MBEANS_ELLIPSIS);
+ hotspotMI.setMnemonic(Resources.getMnemonicInt(Messages.HOTSPOT_MBEANS_ELLIPSIS));
+ hotspotMI.setAccelerator(KeyStroke.
+ getKeyStroke(KeyEvent.VK_H,
+ InputEvent.CTRL_DOWN_MASK));
+ hotspotMI.addActionListener(this);
+ connectionMenu.add(hotspotMI);
+
+ connectionMenu.addSeparator();
+ }
+
+ connectMI = new JMenuItem(Messages.NEW_CONNECTION_ELLIPSIS);
+ connectMI.setMnemonic(Resources.getMnemonicInt(Messages.NEW_CONNECTION_ELLIPSIS));
+ connectMI.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N,
+ InputEvent.CTRL_DOWN_MASK));
+ connectMI.addActionListener(this);
+ connectionMenu.add(connectMI);
+
+ connectionMenu.addSeparator();
+
+ exitMI = new JMenuItem(Messages.EXIT);
+ exitMI.setMnemonic(Resources.getMnemonicInt(Messages.EXIT));
+ exitMI.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F4,
+ InputEvent.ALT_DOWN_MASK));
+ exitMI.addActionListener(this);
+ connectionMenu.add(exitMI);
+
+
+ JMenu helpMenu = new JMenu(Messages.HELP_MENU_TITLE);
+ helpMenu.setMnemonic(Resources.getMnemonicInt(Messages.HELP_MENU_TITLE));
+ menuBar.add(helpMenu);
+
+ if (AboutDialog.isBrowseSupported()) {
+ userGuideMI = new JMenuItem(Messages.HELP_MENU_USER_GUIDE_TITLE);
+ userGuideMI.setMnemonic(Resources.getMnemonicInt(Messages.HELP_MENU_USER_GUIDE_TITLE));
+ userGuideMI.addActionListener(this);
+ helpMenu.add(userGuideMI);
+ helpMenu.addSeparator();
+ }
+ aboutMI = new JMenuItem(Messages.HELP_MENU_ABOUT_TITLE);
+ aboutMI.setMnemonic(Resources.getMnemonicInt(Messages.HELP_MENU_ABOUT_TITLE));
+ aboutMI.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F1, 0));
+ aboutMI.addActionListener(this);
+ helpMenu.add(aboutMI);
+ }
+
+ public JDesktopPane getDesktopPane() {
+ return desktop;
+ }
+
+ public List<VMInternalFrame> getInternalFrames() {
+ return windows;
+ }
+
+ private void createMDI() {
+ // Restore title - we now show connection name on internal frames
+ setTitle(title);
+
+ Container cp = getContentPane();
+ Component oldCenter =
+ ((BorderLayout)cp.getLayout()).
+ getLayoutComponent(BorderLayout.CENTER);
+
+ windowMenu = new WindowMenu(Messages.WINDOW);
+ windowMenu.setMnemonic(Resources.getMnemonicInt(Messages.WINDOW));
+ // Add Window menu before Help menu
+ menuBar.add(windowMenu, menuBar.getComponentCount() - 1);
+
+ desktop = new JDesktopPane();
+ desktop.setBackground(new Color(235, 245, 255));
+
+ cp.add(desktop, BorderLayout.CENTER);
+
+ if (oldCenter instanceof VMPanel) {
+ addFrame((VMPanel)oldCenter);
+ }
+ }
+
+ private class WindowMenu extends JMenu {
+ VMInternalFrame[] windowMenuWindows = new VMInternalFrame[0];
+ int separatorPosition;
+
+ // The width value of viewR is used to truncate long menu items.
+ // The rest are placeholders and are ignored for this purpose.
+ Rectangle viewR = new Rectangle(0, 0, 400, 20);
+ Rectangle textR = new Rectangle(0, 0, 0, 0);
+ Rectangle iconR = new Rectangle(0, 0, 0, 0);
+
+ WindowMenu(String text) {
+ super(text);
+
+ cascadeMI = new JMenuItem(Messages.CASCADE);
+ cascadeMI.setMnemonic(Resources.getMnemonicInt(Messages.CASCADE));
+ cascadeMI.addActionListener(JConsole.this);
+ add(cascadeMI);
+
+ tileMI = new JMenuItem(Messages.TILE);
+ tileMI.setMnemonic(Resources.getMnemonicInt(Messages.TILE));
+ tileMI.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_T,
+ InputEvent.CTRL_DOWN_MASK));
+ tileMI.addActionListener(JConsole.this);
+ add(tileMI);
+
+ minimizeAllMI = new JMenuItem(Messages.MINIMIZE_ALL);
+ minimizeAllMI.setMnemonic(Resources.getMnemonicInt(Messages.MINIMIZE_ALL));
+ minimizeAllMI.addActionListener(JConsole.this);
+ add(minimizeAllMI);
+
+ restoreAllMI = new JMenuItem(Messages.RESTORE_ALL);
+ restoreAllMI.setMnemonic(Resources.getMnemonicInt(Messages.RESTORE_ALL));
+ restoreAllMI.addActionListener(JConsole.this);
+ add(restoreAllMI);
+
+ separatorPosition = getMenuComponentCount();
+ }
+
+ private void add(VMInternalFrame vmIF) {
+ if (separatorPosition == getMenuComponentCount()) {
+ addSeparator();
+ }
+
+ int index = -1;
+ int position = separatorPosition + 1;
+ int n = windowMenuWindows.length;
+
+ for (int i = 0; i < n; i++) {
+ if (windowMenuWindows[i] != null) {
+ // Slot is in use, try next
+ position++;
+ } else {
+ // Found a free slot
+ index = i;
+ break;
+ }
+ }
+
+ if (index == -1) {
+ // Create a slot at the end
+ VMInternalFrame[] newArray = new VMInternalFrame[n + 1];
+ System.arraycopy(windowMenuWindows, 0, newArray, 0, n);
+ windowMenuWindows = newArray;
+ index = n;
+ }
+
+ windowMenuWindows[index] = vmIF;
+
+ String indexString = "" + (index+1);
+ String vmName = vmIF.getVMPanel().getDisplayName();
+ // Maybe truncate menu item string and end with "..."
+ String text =
+ SwingUtilities.layoutCompoundLabel(this,
+ getGraphics().getFontMetrics(getFont()),
+ indexString + " " + vmName,
+ null, 0, 0, 0, 0,
+ viewR, iconR, textR, 0);
+ JMenuItem mi = new JMenuItem(text);
+ if (text.endsWith("...")) {
+ mi.setToolTipText(vmName);
+ }
+
+ // Set mnemonic using last digit of number
+ int nDigits = indexString.length();
+ mi.setMnemonic(indexString.charAt(nDigits-1));
+ mi.setDisplayedMnemonicIndex(nDigits-1);
+
+ mi.putClientProperty("JConsole.vmIF", vmIF);
+ mi.addActionListener(JConsole.this);
+ vmIF.putClientProperty("JConsole.menuItem", mi);
+ add(mi, position);
+ }
+
+ private void remove(VMInternalFrame vmIF) {
+ for (int i = 0; i < windowMenuWindows.length; i++) {
+ if (windowMenuWindows[i] == vmIF) {
+ windowMenuWindows[i] = null;
+ }
+ }
+ JMenuItem mi = (JMenuItem)vmIF.getClientProperty("JConsole.menuItem");
+ remove(mi);
+ mi.putClientProperty("JConsole.vmIF", null);
+ vmIF.putClientProperty("JConsole.menuItem", null);
+
+ if (separatorPosition == getMenuComponentCount() - 1) {
+ remove(getMenuComponent(getMenuComponentCount() - 1));
+ }
+ }
+ }
+
+ public void actionPerformed(ActionEvent ev) {
+ Object src = ev.getSource();
+ if (src == hotspotMI) {
+ showCreateMBeanDialog();
+ }
+
+ if (src == connectButton || src == connectMI) {
+ VMPanel vmPanel = null;
+ JInternalFrame vmIF = desktop.getSelectedFrame();
+ if (vmIF instanceof VMInternalFrame) {
+ vmPanel = ((VMInternalFrame)vmIF).getVMPanel();
+ }
+ String hostName = "";
+ String url = "";
+ if (vmPanel != null) {
+ hostName = vmPanel.getHostName();
+ if(vmPanel.getUrl() != null)
+ url = vmPanel.getUrl();
+ }
+ showConnectDialog(url, hostName, 0, null, null, null);
+ } else if (src == tileMI) {
+ tileWindows();
+ } else if (src == cascadeMI) {
+ cascadeWindows();
+ } else if (src == minimizeAllMI) {
+ for (VMInternalFrame vmIF : windows) {
+ try {
+ vmIF.setIcon(true);
+ } catch (PropertyVetoException ex) {
+ // Ignore
+ }
+ }
+ } else if (src == restoreAllMI) {
+ for (VMInternalFrame vmIF : windows) {
+ try {
+ vmIF.setIcon(false);
+ } catch (PropertyVetoException ex) {
+ // Ignore
+ }
+ }
+ } else if (src == exitMI) {
+ System.exit(0);
+ } else if (src == userGuideMI) {
+ AboutDialog.browseUserGuide(this);
+ } else if (src == aboutMI) {
+ AboutDialog.showAboutDialog(this);
+ } else if (src instanceof JMenuItem) {
+ JMenuItem mi = (JMenuItem)src;
+ VMInternalFrame vmIF = (VMInternalFrame)mi.
+ getClientProperty("JConsole.vmIF");
+ if (vmIF != null) {
+ try {
+ vmIF.setIcon(false);
+ vmIF.setSelected(true);
+ } catch (PropertyVetoException ex) {
+ // Ignore
+ }
+ vmIF.moveToFront();
+ }
+ }
+ }
+
+
+ public void tileWindows() {
+ int w = -1;
+ int h = -1;
+ int n = 0;
+ for (VMInternalFrame vmIF : windows) {
+ if (!vmIF.isIcon()) {
+ n++;
+ if (w == -1) {
+ try {
+ vmIF.setMaximum(true);
+ w = vmIF.getWidth();
+ h = vmIF.getHeight();
+ } catch (PropertyVetoException ex) {
+ // Ignore
+ }
+ }
+ }
+ }
+ if (n > 0 && w > 0 && h > 0) {
+ int rows = (int)Math.ceil(Math.sqrt(n));
+ int cols = n / rows;
+ if (rows * cols < n) cols++;
+ int x = 0;
+ int y = 0;
+ w /= cols;
+ h /= rows;
+ int col = 0;
+ for (VMInternalFrame vmIF : windows) {
+ if (!vmIF.isIcon()) {
+ try {
+ vmIF.setMaximum(n==1);
+ } catch (PropertyVetoException ex) {
+ // Ignore
+ }
+ if (n > 1) {
+ vmIF.setBounds(x, y, w, h);
+ }
+ if (col < cols-1) {
+ col++;
+ x += w;
+ } else {
+ col = 0;
+ x = 0;
+ y += h;
+ }
+ }
+ }
+ }
+ }
+
+ public void cascadeWindows() {
+ int n = 0;
+ int w = -1;
+ int h = -1;
+ for (VMInternalFrame vmIF : windows) {
+ if (!vmIF.isIcon()) {
+ try {
+ vmIF.setMaximum(false);
+ } catch (PropertyVetoException ex) {
+ // Ignore
+ }
+ n++;
+ vmIF.pack();
+ if (w == -1) {
+ try {
+ w = vmIF.getWidth();
+ h = vmIF.getHeight();
+ vmIF.setMaximum(true);
+ w = vmIF.getWidth() - w;
+ h = vmIF.getHeight() - h;
+ vmIF.pack();
+ } catch (PropertyVetoException ex) {
+ // Ignore
+ }
+ }
+ }
+ }
+ int x = 0;
+ int y = 0;
+ int dX = (n > 1) ? (w / (n - 1)) : 0;
+ int dY = (n > 1) ? (h / (n - 1)) : 0;
+ for (VMInternalFrame vmIF : windows) {
+ if (!vmIF.isIcon()) {
+ vmIF.setLocation(x, y);
+ vmIF.moveToFront();
+ x += dX;
+ y += dY;
+ }
+ }
+ }
+
+ // Call on EDT
+ void addHost(String hostName, int port,
+ String userName, String password) {
+ addHost(hostName, port, userName, password, false);
+ }
+
+ // Call on EDT
+ void addVmid(LocalVirtualMachine lvm) {
+ addVmid(lvm, false);
+ }
+
+ // Call on EDT
+ void addVmid(final LocalVirtualMachine lvm, final boolean tile) {
+ new Thread("JConsole.addVmid") {
+ public void run() {
+ try {
+ addProxyClient(ProxyClient.getProxyClient(lvm), tile);
+ } catch (final SecurityException ex) {
+ failed(ex, null, null, null);
+ } catch (final IOException ex) {
+ failed(ex, null, null, null);
+ }
+ }
+ }.start();
+ }
+
+ // Call on EDT
+ void addUrl(final String url,
+ final String userName,
+ final String password,
+ final boolean tile) {
+ new Thread("JConsole.addUrl") {
+ public void run() {
+ try {
+ addProxyClient(ProxyClient.getProxyClient(url, userName, password),
+ tile);
+ } catch (final MalformedURLException ex) {
+ failed(ex, url, userName, password);
+ } catch (final SecurityException ex) {
+ failed(ex, url, userName, password);
+ } catch (final IOException ex) {
+ failed(ex, url, userName, password);
+ }
+ }
+ }.start();
+ }
+
+
+ // Call on EDT
+ void addHost(final String hostName, final int port,
+ final String userName, final String password,
+ final boolean tile) {
+ new Thread("JConsole.addHost") {
+ public void run() {
+ try {
+ addProxyClient(ProxyClient.getProxyClient(hostName, port,
+ userName, password),
+ tile);
+ } catch (final IOException ex) {
+ dbgStackTrace(ex);
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ showConnectDialog(null, hostName, port,
+ userName, password, errorMessage(ex));
+ }
+ });
+ }
+ }
+ }.start();
+ }
+
+
+ // Call on worker thread
+ void addProxyClient(final ProxyClient proxyClient, final boolean tile) {
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ VMPanel vmPanel = new VMPanel(proxyClient, updateInterval);
+ addFrame(vmPanel);
+
+ if (tile) {
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ tileWindows();
+ }
+ });
+ }
+ vmPanel.connect();
+ }
+ });
+ }
+
+
+ // Call on worker thread
+ private void failed(final Exception ex,
+ final String url,
+ final String userName,
+ final String password) {
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ dbgStackTrace(ex);
+ showConnectDialog(url,
+ null,
+ -1,
+ userName,
+ password,
+ errorMessage(ex));
+ }
+ });
+ }
+
+
+ private VMInternalFrame addFrame(VMPanel vmPanel) {
+ final VMInternalFrame vmIF = new VMInternalFrame(vmPanel);
+
+ for (VMInternalFrame f : windows) {
+ try {
+ f.setMaximum(false);
+ } catch (PropertyVetoException ex) {
+ // Ignore
+ }
+ }
+ desktop.add(vmIF);
+
+ vmIF.setLocation(frameLoc, frameLoc);
+ frameLoc += 30;
+ vmIF.setVisible(true);
+ windows.add(vmIF);
+ if (windows.size() == 1) {
+ try {
+ vmIF.setMaximum(true);
+ } catch (PropertyVetoException ex) {
+ // Ignore
+ }
+ }
+ vmIF.addInternalFrameListener(this);
+ windowMenu.add(vmIF);
+
+ return vmIF;
+ }
+
+ private void showConnectDialog(String url,
+ String hostName,
+ int port,
+ String userName,
+ String password,
+ String msg) {
+ if (connectDialog == null) {
+ connectDialog = new ConnectDialog(this);
+ }
+ connectDialog.setConnectionParameters(url,
+ hostName,
+ port,
+ userName,
+ password,
+ msg);
+
+ connectDialog.refresh();
+ connectDialog.setVisible(true);
+ try {
+ // Bring to front of other dialogs
+ connectDialog.setSelected(true);
+ } catch (PropertyVetoException e) {
+ }
+ }
+
+ private void showCreateMBeanDialog() {
+ if (createDialog == null) {
+ createDialog = new CreateMBeanDialog(this);
+ }
+ createDialog.setVisible(true);
+ try {
+ // Bring to front of other dialogs
+ createDialog.setSelected(true);
+ } catch (PropertyVetoException e) {
+ }
+ }
+
+ private void removeVMInternalFrame(VMInternalFrame vmIF) {
+ windowMenu.remove(vmIF);
+ desktop.remove(vmIF);
+ desktop.repaint();
+ vmIF.getVMPanel().cleanUp();
+ vmIF.dispose();
+ }
+
+ private boolean isProxyClientUsed(ProxyClient client) {
+ for(VMInternalFrame frame : windows) {
+ ProxyClient cli = frame.getVMPanel().getProxyClient(false);
+ if(client == cli)
+ return true;
+ }
+ return false;
+ }
+
+ static boolean isValidRemoteString(String txt) {
+ boolean valid = false;
+ if (txt != null) {
+ txt = txt.trim();
+ if (txt.startsWith(ROOT_URL)) {
+ if (txt.length() > ROOT_URL.length()) {
+ valid = true;
+ }
+ } else {
+ //---------------------------------------
+ // Supported host and port combinations:
+ // hostname:port
+ // IPv4Address:port
+ // [IPv6Address]:port
+ //---------------------------------------
+
+ // Is literal IPv6 address?
+ //
+ if (txt.startsWith("[")) {
+ int index = txt.indexOf("]:");
+ if (index != -1) {
+ // Extract literal IPv6 address
+ //
+ String address = txt.substring(1, index);
+ if (IPAddressUtil.isIPv6LiteralAddress(address)) {
+ // Extract port
+ //
+ try {
+ String portStr = txt.substring(index + 2);
+ int port = Integer.parseInt(portStr);
+ if (port >= 0 && port <= 0xFFFF) {
+ valid = true;
+ }
+ } catch (NumberFormatException ex) {
+ valid = false;
+ }
+ }
+ }
+ } else {
+ String[] s = txt.split(":");
+ if (s.length == 2) {
+ try {
+ int port = Integer.parseInt(s[1]);
+ if (port >= 0 && port <= 0xFFFF) {
+ valid = true;
+ }
+ } catch (NumberFormatException ex) {
+ valid = false;
+ }
+ }
+ }
+ }
+ }
+ return valid;
+ }
+
+ private String errorMessage(Exception ex) {
+ String msg = Messages.CONNECTION_FAILED;
+ if (ex instanceof IOException || ex instanceof SecurityException) {
+ Throwable cause = null;
+ Throwable c = ex.getCause();
+ while (c != null) {
+ cause = c;
+ c = c.getCause();
+ }
+ if (cause instanceof ConnectException) {
+ return msg + ": " + cause.getMessage();
+ } else if (cause instanceof UnknownHostException) {
+ return Resources.format(Messages.UNKNOWN_HOST, cause.getMessage());
+ } else if (cause instanceof NoRouteToHostException) {
+ return msg + ": " + cause.getMessage();
+ } else if (cause instanceof FailedLoginException) {
+ return msg + ": " + cause.getMessage();
+ } else if (cause instanceof SSLHandshakeException) {
+ return msg + ": "+ cause.getMessage();
+ }
+ } else if (ex instanceof MalformedURLException) {
+ return Resources.format(Messages.INVALID_URL, ex.getMessage());
+ }
+ return msg + ": " + ex.getMessage();
+ }
+
+
+ // InternalFrameListener interface
+
+ public void internalFrameClosing(InternalFrameEvent e) {
+ VMInternalFrame vmIF = (VMInternalFrame)e.getInternalFrame();
+ removeVMInternalFrame(vmIF);
+ windows.remove(vmIF);
+ ProxyClient client = vmIF.getVMPanel().getProxyClient(false);
+ if(!isProxyClientUsed(client))
+ client.markAsDead();
+ if (windows.size() == 0) {
+ showConnectDialog("", "", 0, null, null, null);
+ }
+ }
+
+ public void internalFrameOpened(InternalFrameEvent e) {}
+ public void internalFrameClosed(InternalFrameEvent e) {}
+ public void internalFrameIconified(InternalFrameEvent e) {}
+ public void internalFrameDeiconified(InternalFrameEvent e) {}
+ public void internalFrameActivated(InternalFrameEvent e) {}
+ public void internalFrameDeactivated(InternalFrameEvent e) {}
+
+
+ private static void usage() {
+ System.err.println(Resources.format(Messages.ZZ_USAGE_TEXT, "jconsole"));
+ }
+
+ private static void mainInit(final List<String> urls,
+ final List<String> hostNames,
+ final List<Integer> ports,
+ final List<LocalVirtualMachine> vmids,
+ final ProxyClient proxyClient,
+ final boolean noTile,
+ final boolean hotspot) {
+
+
+ // Always create Swing GUI on the Event Dispatching Thread
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ JConsole jConsole = new JConsole(hotspot);
+
+ // Center the window on screen, taking into account screen
+ // size and insets.
+ Toolkit toolkit = Toolkit.getDefaultToolkit();
+ GraphicsConfiguration gc = jConsole.getGraphicsConfiguration();
+ Dimension scrSize = toolkit.getScreenSize();
+ Insets scrInsets = toolkit.getScreenInsets(gc);
+ Rectangle scrBounds =
+ new Rectangle(scrInsets.left, scrInsets.top,
+ scrSize.width - scrInsets.left - scrInsets.right,
+ scrSize.height - scrInsets.top - scrInsets.bottom);
+ int w = Math.min(900, scrBounds.width);
+ int h = Math.min(750, scrBounds.height);
+ jConsole.setBounds(scrBounds.x + (scrBounds.width - w) / 2,
+ scrBounds.y + (scrBounds.height - h) / 2,
+ w, h);
+
+ jConsole.setVisible(true);
+ jConsole.createMDI();
+
+ for (int i = 0; i < hostNames.size(); i++) {
+ jConsole.addHost(hostNames.get(i), ports.get(i),
+ null, null,
+ (i == hostNames.size() - 1) ?
+ !noTile : false);
+ }
+
+ for (int i = 0; i < urls.size(); i++) {
+ jConsole.addUrl(urls.get(i),
+ null,
+ null,
+ (i == urls.size() - 1) ?
+ !noTile : false);
+ }
+
+ for (int i = 0; i < vmids.size(); i++) {
+ jConsole.addVmid(vmids.get(i),
+ (i == vmids.size() - 1) ?
+ !noTile : false);
+ }
+
+ if (vmids.size() == 0 &&
+ hostNames.size() == 0 &&
+ urls.size() == 0) {
+ jConsole.showConnectDialog(null,
+ null,
+ 0,
+ null,
+ null,
+ null);
+ }
+ }
+ });
+ }
+
+ public static void main(String[] args) {
+ boolean noTile = false, hotspot = false;
+ int argIndex = 0;
+ ProxyClient proxyClient = null;
+
+ if (System.getProperty("jconsole.showOutputViewer") != null) {
+ OutputViewer.init();
+ }
+
+ while (args.length - argIndex > 0 && args[argIndex].startsWith("-")) {
+ String arg = args[argIndex++];
+ if (arg.equals("-h") ||
+ arg.equals("-help") ||
+ arg.equals("-?")) {
+
+ usage();
+ return;
+ } else if (arg.startsWith("-interval=")) {
+ try {
+ updateInterval = Integer.parseInt(arg.substring(10)) *
+ 1000;
+ if (updateInterval <= 0) {
+ usage();
+ return;
+ }
+ } catch (NumberFormatException ex) {
+ usage();
+ return;
+ }
+ } else if (arg.equals("-pluginpath")) {
+ if (argIndex < args.length && !args[argIndex].startsWith("-")) {
+ pluginPath = args[argIndex++];
+ } else {
+ // Invalid argument
+ usage();
+ return;
+ }
+ } else if (arg.equals("-notile")) {
+ noTile = true;
+ } else if (arg.equals("-version")) {
+ Version.print(System.err);
+ return;
+ } else if (arg.equals("-debug")) {
+ debug = true;
+ } else if (arg.equals("-fullversion")) {
+ Version.printFullVersion(System.err);
+ return;
+ } else {
+ // Unknown switch
+ usage();
+ return;
+ }
+ }
+
+ if (System.getProperty("jconsole.showUnsupported") != null) {
+ hotspot = true;
+ }
+
+ List<String> urls = new ArrayList<String>();
+ List<String> hostNames = new ArrayList<String>();
+ List<Integer> ports = new ArrayList<Integer>();
+ List<LocalVirtualMachine> vms = new ArrayList<LocalVirtualMachine>();
+
+ for (int i = argIndex; i < args.length; i++) {
+ String arg = args[i];
+ if (isValidRemoteString(arg)) {
+ if (arg.startsWith(ROOT_URL)) {
+ urls.add(arg);
+ } else if (arg.matches(".*:[0-9]*")) {
+ int p = arg.lastIndexOf(':');
+ hostNames.add(arg.substring(0, p));
+ try {
+ ports.add(Integer.parseInt(arg.substring(p+1)));
+ } catch (NumberFormatException ex) {
+ usage();
+ return;
+ }
+ }
+ } else {
+ if (!isLocalAttachAvailable()) {
+ System.err.println("Local process monitoring is not supported");
+ return;
+ }
+ try {
+ int vmid = Integer.parseInt(arg);
+ LocalVirtualMachine lvm =
+ LocalVirtualMachine.getLocalVirtualMachine(vmid);
+ if (lvm == null) {
+ System.err.println("Invalid process id:" + vmid);
+ return;
+ }
+ vms.add(lvm);
+ } catch (NumberFormatException ex) {
+ usage();
+ return;
+ }
+ }
+ }
+
+ mainInit(urls, hostNames, ports, vms, proxyClient, noTile, hotspot);
+ }
+
+ public static boolean isDebug() {
+ return debug;
+ }
+
+ private static void dbgStackTrace(Exception ex) {
+ if (debug) {
+ ex.printStackTrace();
+ }
+ }
+
+ /**
+ * local attach is supported in this implementation as jdk.jconsole
+ * requires jdk.attach and jdk.management.agent
+ */
+ public static boolean isLocalAttachAvailable() {
+ return true;
+ }
+
+
+ private static ServiceLoader<JConsolePlugin> pluginService = null;
+
+ // Return a list of newly instantiated JConsolePlugin objects
+ static synchronized List<JConsolePlugin> getPlugins() {
+ if (pluginService == null) {
+ // First time loading and initializing the plugins
+ initPluginService(pluginPath);
+ } else {
+ // reload the plugin so that new instances will be created
+ pluginService.reload();
+ }
+
+ List<JConsolePlugin> plugins = new ArrayList<JConsolePlugin>();
+ for (JConsolePlugin p : pluginService) {
+ plugins.add(p);
+ }
+ return plugins;
+ }
+
+ private static void initPluginService(String pluginPath) {
+ if (pluginPath.length() > 0) {
+ try {
+ ClassLoader pluginCL = new URLClassLoader(pathToURLs(pluginPath));
+ ServiceLoader<JConsolePlugin> plugins =
+ ServiceLoader.load(JConsolePlugin.class, pluginCL);
+ // validate all plugins
+ for (JConsolePlugin p : plugins) {
+ if (isDebug()) {
+ System.out.println("Plugin " + p.getClass() + " loaded.");
+ }
+ }
+ pluginService = plugins;
+ } catch (ServiceConfigurationError e) {
+ // Error occurs during initialization of plugin
+ System.out.println(Resources.format(Messages.FAIL_TO_LOAD_PLUGIN,
+ e.getMessage()));
+ } catch (MalformedURLException e) {
+ if (JConsole.isDebug()) {
+ e.printStackTrace();
+ }
+ System.out.println(Resources.format(Messages.INVALID_PLUGIN_PATH,
+ e.getMessage()));
+ }
+ }
+
+ if (pluginService == null) {
+ initEmptyPlugin();
+ }
+ }
+
+ private static void initEmptyPlugin() {
+ ClassLoader pluginCL = new URLClassLoader(new URL[0]);
+ pluginService = ServiceLoader.load(JConsolePlugin.class, pluginCL);
+ }
+
+ /**
+ * Utility method for converting a search path string to an array
+ * of directory and JAR file URLs.
+ *
+ * @param path the search path string
+ * @return the resulting array of directory and JAR file URLs
+ */
+ private static URL[] pathToURLs(String path) throws MalformedURLException {
+ String[] names = path.split(File.pathSeparator);
+ URL[] urls = new URL[names.length];
+ int count = 0;
+ for (String f : names) {
+ URL url = fileToURL(new File(f));
+ urls[count++] = url;
+ }
+ return urls;
+ }
+
+ /**
+ * Returns the directory or JAR file URL corresponding to the specified
+ * local file name.
+ *
+ * @param file the File object
+ * @return the resulting directory or JAR file URL, or null if unknown
+ */
+ private static URL fileToURL(File file) throws MalformedURLException {
+ String name;
+ try {
+ name = file.getCanonicalPath();
+ } catch (IOException e) {
+ name = file.getAbsolutePath();
+ }
+ name = name.replace(File.separatorChar, '/');
+ if (!name.startsWith("/")) {
+ name = "/" + name;
+ }
+ // If the file does not exist, then assume that it's a directory
+ if (!file.isFile()) {
+ name = name + "/";
+ }
+ return new URL("file", "", name);
+ }
+
+
+ private static class FixedJRootPane extends JRootPane {
+ public void updateUI() {
+ updateLafValues();
+ super.updateUI();
+ }
+
+ /**
+ * The revalidate method seems to be the only one that gets
+ * called whenever there is a change of L&F or change of theme
+ * in Windows L&F and GTK L&F.
+ */
+ @Override
+ public void revalidate() {
+ // Workaround for Swing bug where the titledborder in both
+ // GTK and Windows L&F's use calculated colors instead of
+ // the highlight/shadow colors from the theme.
+ //
+ // Putting null removes any previous override and causes a
+ // fallback to the current L&F's value.
+ UIManager.put("TitledBorder.border", null);
+ Border border = UIManager.getBorder("TitledBorder.border");
+ if (border instanceof BorderUIResource.EtchedBorderUIResource) {
+ Color highlight = UIManager.getColor("ToolBar.highlight");
+ Color shadow = UIManager.getColor("ToolBar.shadow");
+ border = new BorderUIResource.EtchedBorderUIResource(highlight,
+ shadow);
+ UIManager.put("TitledBorder.border", border);
+ }
+
+ if (IS_GTK) {
+ // Workaround for Swing bug where the titledborder in
+ // GTK L&F use hardcoded color and font for the title
+ // instead of getting them from the theme.
+ UIManager.put("TitledBorder.titleColor",
+ UIManager.getColor("Label.foreground"));
+ UIManager.put("TitledBorder.font",
+ UIManager.getFont("Label.font"));
+ }
+ super.revalidate();
+ }
+ }
+}