/* * 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 windows = new ArrayList(); 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 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 urls, final List hostNames, final List ports, final List 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 urls = new ArrayList(); List hostNames = new ArrayList(); List ports = new ArrayList(); List vms = new ArrayList(); 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(); } } private static final boolean localAttachmentSupported; static { boolean supported; try { Class.forName("com.sun.tools.attach.VirtualMachine"); Class.forName("sun.management.ConnectorAddressLink"); supported = true; } catch (NoClassDefFoundError x) { supported = false; } catch (ClassNotFoundException x) { supported = false; } localAttachmentSupported = supported; } public static boolean isLocalAttachAvailable() { return localAttachmentSupported; } private static ServiceLoader pluginService = null; // Return a list of newly instantiated JConsolePlugin objects static synchronized List 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 plugins = new ArrayList(); 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 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(); } } }