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