Path: blob/master/src/jdk.jconsole/share/classes/sun/tools/jconsole/ConnectDialog.java
40948 views
/*1* Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.tools.jconsole;2627import java.util.List;28import java.awt.*;29import java.awt.event.*;30import java.util.*;3132import javax.swing.*;33import javax.swing.border.*;34import javax.swing.event.*;35import javax.swing.plaf.basic.BasicRadioButtonUI;36import javax.swing.table.*;37383940import static java.awt.BorderLayout.*;41import static javax.swing.ListSelectionModel.*;42import static sun.tools.jconsole.Utilities.*;4344@SuppressWarnings("serial")45public class ConnectDialog extends InternalDialog46implements DocumentListener, FocusListener,47ItemListener, ListSelectionListener, KeyListener {4849private static final int COL_NAME = 0;50private static final int COL_PID = 1;515253JConsole jConsole;54JTextField userNameTF, passwordTF;55JRadioButton localRadioButton, remoteRadioButton;56JLabel localMessageLabel, remoteMessageLabel;57JTextField remoteTF;58JButton connectButton, cancelButton;59JPanel radioButtonPanel;6061private Icon mastheadIcon =62new MastheadIcon(Messages.CONNECT_DIALOG_MASTHEAD_TITLE);63private Color hintTextColor, disabledTableCellColor;6465// The table of managed VM (local process)66JTable vmTable;67ManagedVmTableModel vmModel = null;6869JScrollPane localTableScrollPane = null;7071private Action connectAction, cancelAction;727374public ConnectDialog(JConsole jConsole) {75super(jConsole, Messages.CONNECT_DIALOG_TITLE, true);7677this.jConsole = jConsole;78setAccessibleDescription(this,79Messages.CONNECT_DIALOG_ACCESSIBLE_DESCRIPTION);80setDefaultCloseOperation(HIDE_ON_CLOSE);81setResizable(false);82Container cp = (JComponent)getContentPane();8384radioButtonPanel = new JPanel(new BorderLayout(0, 12));85radioButtonPanel.setBorder(new EmptyBorder(6, 12, 12, 12));86ButtonGroup radioButtonGroup = new ButtonGroup();87JPanel bottomPanel = new JPanel(new BorderLayout());8889statusBar = new JLabel(" ", JLabel.CENTER);90setAccessibleName(statusBar,91Messages.CONNECT_DIALOG_STATUS_BAR_ACCESSIBLE_NAME);9293Font normalLabelFont = statusBar.getFont();94Font boldLabelFont = normalLabelFont.deriveFont(Font.BOLD);95Font smallLabelFont = normalLabelFont.deriveFont(normalLabelFont.getSize2D() - 1);9697JLabel mastheadLabel = new JLabel(mastheadIcon);98setAccessibleName(mastheadLabel,99Messages.CONNECT_DIALOG_MASTHEAD_ACCESSIBLE_NAME);100101cp.add(mastheadLabel, NORTH);102cp.add(radioButtonPanel, CENTER);103cp.add(bottomPanel, SOUTH);104105createActions();106107remoteTF = new JTextField();108remoteTF.addActionListener(connectAction);109remoteTF.getDocument().addDocumentListener(this);110remoteTF.addFocusListener(this);111remoteTF.setPreferredSize(remoteTF.getPreferredSize());112setAccessibleName(remoteTF,113Messages.REMOTE_PROCESS_TEXT_FIELD_ACCESSIBLE_NAME);114115//116// If the VM supports the local attach mechanism (is: Sun117// implementation) then the Local Process panel is created.118//119if (JConsole.isLocalAttachAvailable()) {120vmModel = new ManagedVmTableModel();121vmTable = new LocalTabJTable(vmModel);122vmTable.setSelectionMode(SINGLE_SELECTION);123vmTable.setPreferredScrollableViewportSize(new Dimension(400, 250));124vmTable.setColumnSelectionAllowed(false);125vmTable.addFocusListener(this);126vmTable.getSelectionModel().addListSelectionListener(this);127128TableColumnModel columnModel = vmTable.getColumnModel();129130TableColumn pidColumn = columnModel.getColumn(COL_PID);131pidColumn.setMaxWidth(getLabelWidth("9999999"));132pidColumn.setResizable(false);133134TableColumn cmdLineColumn = columnModel.getColumn(COL_NAME);135cmdLineColumn.setResizable(false);136137localRadioButton = new JRadioButton(Messages.LOCAL_PROCESS_COLON);138localRadioButton.setMnemonic(Resources.getMnemonicInt(Messages.LOCAL_PROCESS_COLON));139localRadioButton.setFont(boldLabelFont);140localRadioButton.addItemListener(this);141radioButtonGroup.add(localRadioButton);142143JPanel localPanel = new JPanel(new BorderLayout());144145JPanel localTablePanel = new JPanel(new BorderLayout());146147radioButtonPanel.add(localPanel, NORTH);148149localPanel.add(localRadioButton, NORTH);150localPanel.add(new Padder(localRadioButton), LINE_START);151localPanel.add(localTablePanel, CENTER);152153localTableScrollPane = new JScrollPane(vmTable);154155localTablePanel.add(localTableScrollPane, NORTH);156157localMessageLabel = new JLabel(" ");158localMessageLabel.setFont(smallLabelFont);159localMessageLabel.setForeground(hintTextColor);160localTablePanel.add(localMessageLabel, SOUTH);161}162163remoteRadioButton = new JRadioButton(Messages.REMOTE_PROCESS_COLON);164remoteRadioButton.setMnemonic(Resources.getMnemonicInt(Messages.REMOTE_PROCESS_COLON));165remoteRadioButton.setFont(boldLabelFont);166radioButtonGroup.add(remoteRadioButton);167168JPanel remotePanel = new JPanel(new BorderLayout());169if (localRadioButton != null) {170remotePanel.add(remoteRadioButton, NORTH);171remotePanel.add(new Padder(remoteRadioButton), LINE_START);172173Action nextRadioButtonAction =174new AbstractAction("nextRadioButton") {175public void actionPerformed(ActionEvent ev) {176JRadioButton rb =177(ev.getSource() == localRadioButton) ? remoteRadioButton178: localRadioButton;179rb.doClick();180rb.requestFocus();181}182};183184localRadioButton.getActionMap().put("nextRadioButton", nextRadioButtonAction);185remoteRadioButton.getActionMap().put("nextRadioButton", nextRadioButtonAction);186187localRadioButton.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0),188"nextRadioButton");189remoteRadioButton.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0),190"nextRadioButton");191} else {192JLabel remoteLabel = new JLabel(remoteRadioButton.getText());193remoteLabel.setFont(boldLabelFont);194remotePanel.add(remoteLabel, NORTH);195}196radioButtonPanel.add(remotePanel, SOUTH);197198JPanel remoteTFPanel = new JPanel(new BorderLayout());199remotePanel.add(remoteTFPanel, CENTER);200201remoteTFPanel.add(remoteTF, NORTH);202203remoteMessageLabel = new JLabel("<html>" + Messages.REMOTE_TF_USAGE + "</html>");204remoteMessageLabel.setFont(smallLabelFont);205remoteMessageLabel.setForeground(hintTextColor);206remoteTFPanel.add(remoteMessageLabel, CENTER);207208JPanel userPwdPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 0, 0));209userPwdPanel.setBorder(new EmptyBorder(12, 0, 0, 0)); // top padding210211int tfWidth = JConsole.IS_WIN ? 12 : 8;212213userNameTF = new JTextField(tfWidth);214userNameTF.addActionListener(connectAction);215userNameTF.getDocument().addDocumentListener(this);216userNameTF.addFocusListener(this);217setAccessibleName(userNameTF,218Messages.USERNAME_ACCESSIBLE_NAME);219LabeledComponent lc;220lc = new LabeledComponent(Messages.USERNAME_COLON_,221Resources.getMnemonicInt(Messages.USERNAME_COLON_),222userNameTF);223lc.label.setFont(boldLabelFont);224userPwdPanel.add(lc);225226passwordTF = new JPasswordField(tfWidth);227// Heights differ, so fix here228passwordTF.setPreferredSize(userNameTF.getPreferredSize());229passwordTF.addActionListener(connectAction);230passwordTF.getDocument().addDocumentListener(this);231passwordTF.addFocusListener(this);232setAccessibleName(passwordTF,233Messages.PASSWORD_ACCESSIBLE_NAME);234235lc = new LabeledComponent(Messages.PASSWORD_COLON_,236Resources.getMnemonicInt(Messages.PASSWORD_COLON_),237passwordTF);238lc.setBorder(new EmptyBorder(0, 12, 0, 0)); // Left padding239lc.label.setFont(boldLabelFont);240userPwdPanel.add(lc);241242remoteTFPanel.add(userPwdPanel, SOUTH);243244String connectButtonToolTipText =245Messages.CONNECT_DIALOG_CONNECT_BUTTON_TOOLTIP;246connectButton = new JButton(connectAction);247connectButton.setToolTipText(connectButtonToolTipText);248249cancelButton = new JButton(cancelAction);250251JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.TRAILING));252buttonPanel.setBorder(new EmptyBorder(12, 12, 2, 12));253if (JConsole.IS_GTK) {254buttonPanel.add(cancelButton);255buttonPanel.add(connectButton);256} else {257buttonPanel.add(connectButton);258buttonPanel.add(cancelButton);259}260bottomPanel.add(buttonPanel, NORTH);261262bottomPanel.add(statusBar, SOUTH);263264updateButtonStates();265Utilities.updateTransparency(this);266}267268public void revalidate() {269// Adjust some colors270Color disabledForeground = UIManager.getColor("Label.disabledForeground");271if (disabledForeground == null) {272// fall back for Nimbus that doesn't support 'Label.disabledForeground'273disabledForeground = UIManager.getColor("Label.disabledText");274}275hintTextColor =276ensureContrast(disabledForeground,277UIManager.getColor("Panel.background"));278disabledTableCellColor =279ensureContrast(new Color(0x808080),280UIManager.getColor("Table.background"));281282if (remoteMessageLabel != null) {283remoteMessageLabel.setForeground(hintTextColor);284// Update html color setting285String colorStr =286String.format("%06x", hintTextColor.getRGB() & 0xFFFFFF);287remoteMessageLabel.setText("<html><font color=#" + colorStr + ">" +288Messages.REMOTE_TF_USAGE);289}290if (localMessageLabel != null) {291localMessageLabel.setForeground(hintTextColor);292// Update html color setting293valueChanged(null);294}295296super.revalidate();297}298299private void createActions() {300connectAction = new AbstractAction(Messages.CONNECT) {301/* init */ {302putValue(Action.MNEMONIC_KEY, Resources.getMnemonicInt(Messages.CONNECT));303}304305public void actionPerformed(ActionEvent ev) {306if (!isEnabled() || !isVisible()) {307return;308}309setVisible(false);310statusBar.setText("");311312if (remoteRadioButton.isSelected()) {313String txt = remoteTF.getText().trim();314String userName = userNameTF.getText().trim();315userName = userName.isEmpty() ? null : userName;316String password = passwordTF.getText();317password = password.isEmpty() ? null : password;318try {319if (txt.startsWith(JConsole.ROOT_URL)) {320String url = txt;321jConsole.addUrl(url, userName, password, false);322remoteTF.setText(JConsole.ROOT_URL);323return;324} else {325String host = remoteTF.getText().trim();326String port = "0";327int index = host.lastIndexOf(':');328if (index >= 0) {329port = host.substring(index + 1);330host = host.substring(0, index);331}332if (host.length() > 0 && port.length() > 0) {333int p = Integer.parseInt(port.trim());334jConsole.addHost(host, p, userName, password);335remoteTF.setText("");336userNameTF.setText("");337passwordTF.setText("");338return;339}340}341} catch (Exception ex) {342statusBar.setText(ex.toString());343}344setVisible(true);345} else if (localRadioButton != null && localRadioButton.isSelected()) {346// Try to connect to selected VM. If a connection347// cannot be established for some reason (the process has348// terminated for example) then keep the dialog open showing349// the connect error.350//351int row = vmTable.getSelectedRow();352if (row >= 0) {353jConsole.addVmid(vmModel.vmAt(row));354}355refresh();356}357}358};359360cancelAction = new AbstractAction(Messages.CANCEL) {361public void actionPerformed(ActionEvent ev) {362setVisible(false);363statusBar.setText("");364}365};366}367368369// a label used solely for calculating the width370private static JLabel tmpLabel = new JLabel();371public static int getLabelWidth(String text) {372tmpLabel.setText(text);373return (int) tmpLabel.getPreferredSize().getWidth() + 1;374}375376private class LocalTabJTable extends JTable {377ManagedVmTableModel vmModel;378Border rendererBorder = new EmptyBorder(0, 6, 0, 6);379380public LocalTabJTable(ManagedVmTableModel model) {381super(model);382this.vmModel = model;383384// Remove vertical lines, expect for GTK L&F.385// (because GTK doesn't show header dividers)386if (!JConsole.IS_GTK) {387setShowVerticalLines(false);388setIntercellSpacing(new Dimension(0, 1));389}390391// Double-click handler392addMouseListener(new MouseAdapter() {393public void mouseClicked(MouseEvent evt) {394if (evt.getClickCount() == 2) {395connectButton.doClick();396}397}398});399400// Enter should call default action401getActionMap().put("connect", connectAction);402InputMap inputMap = getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);403inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "connect");404}405406public String getToolTipText(MouseEvent e) {407String tip = null;408java.awt.Point p = e.getPoint();409int rowIndex = rowAtPoint(p);410int colIndex = columnAtPoint(p);411int realColumnIndex = convertColumnIndexToModel(colIndex);412413if (realColumnIndex == COL_NAME) {414LocalVirtualMachine vmd = vmModel.vmAt(rowIndex);415tip = vmd.toString();416}417return tip;418}419420public TableCellRenderer getCellRenderer(int row, int column) {421return new DefaultTableCellRenderer() {422public Component getTableCellRendererComponent(JTable table,423Object value,424boolean isSelected,425boolean hasFocus,426int row,427int column) {428Component comp =429super.getTableCellRendererComponent(table, value, isSelected,430hasFocus, row, column);431432if (!isSelected) {433LocalVirtualMachine lvm = vmModel.vmAt(row);434if (!lvm.isManageable() && !lvm.isAttachable()) {435comp.setForeground(disabledTableCellColor);436}437}438439if (comp instanceof JLabel) {440JLabel label = (JLabel)comp;441label.setBorder(rendererBorder);442443if (value instanceof Integer) {444label.setHorizontalAlignment(JLabel.RIGHT);445}446}447448return comp;449}450};451}452}453454public void setConnectionParameters(String url,455String host,456int port,457String userName,458String password,459String msg) {460if ((url != null && url.length() > 0) ||461(host != null && host.length() > 0 && port > 0)) {462463remoteRadioButton.setSelected(true);464if (url != null && url.length() > 0) {465remoteTF.setText(url);466} else {467remoteTF.setText(host+":"+port);468}469userNameTF.setText((userName != null) ? userName : "");470passwordTF.setText((password != null) ? password : "");471472statusBar.setText((msg != null) ? msg : "");473if (getPreferredSize().width > getWidth()) {474pack();475}476remoteTF.requestFocus();477remoteTF.selectAll();478}479}480481482public void itemStateChanged(ItemEvent ev) {483if (!localRadioButton.isSelected()) {484vmTable.getSelectionModel().clearSelection();485}486updateButtonStates();487}488489private void updateButtonStates() {490boolean connectEnabled = false;491492if (remoteRadioButton.isSelected()) {493connectEnabled = JConsole.isValidRemoteString(remoteTF.getText());494} else if (localRadioButton != null && localRadioButton.isSelected()) {495int row = vmTable.getSelectedRow();496if (row >= 0) {497LocalVirtualMachine lvm = vmModel.vmAt(row);498connectEnabled = (lvm.isManageable() || lvm.isAttachable());499}500}501502connectAction.setEnabled(connectEnabled);503}504505public void insertUpdate(DocumentEvent e) {506updateButtonStates();507}508509public void removeUpdate(DocumentEvent e) {510updateButtonStates();511}512513public void changedUpdate(DocumentEvent e) {514updateButtonStates();515}516517public void focusGained(FocusEvent e) {518Object source = e.getSource();519Component opposite = e.getOppositeComponent();520521if (!e.isTemporary() &&522source instanceof JTextField &&523opposite instanceof JComponent &&524SwingUtilities.getRootPane(opposite) == getRootPane()) {525526((JTextField)source).selectAll();527}528529if (source == remoteTF) {530remoteRadioButton.setSelected(true);531} else if (source == vmTable) {532localRadioButton.setSelected(true);533if (vmModel.getRowCount() == 1) {534// if there's only one process then select the row535vmTable.setRowSelectionInterval(0, 0);536}537}538updateButtonStates();539}540541public void focusLost(FocusEvent e) {542}543544public void keyTyped(KeyEvent e) {545char c = e.getKeyChar();546if (c == KeyEvent.VK_ESCAPE) {547setVisible(false);548} else if (!(Character.isDigit(c) ||549c == KeyEvent.VK_BACK_SPACE ||550c == KeyEvent.VK_DELETE)) {551getToolkit().beep();552e.consume();553}554}555556public void setVisible(boolean b) {557boolean wasVisible = isVisible();558super.setVisible(b);559if (b && !wasVisible) {560SwingUtilities.invokeLater(new Runnable() {561public void run() {562if (remoteRadioButton.isSelected()) {563remoteTF.requestFocus();564remoteTF.selectAll();565}566}567});568}569}570571public void keyPressed(KeyEvent e) {572}573574public void keyReleased(KeyEvent e) {575}576577578// ListSelectionListener interface579public void valueChanged(ListSelectionEvent e) {580updateButtonStates();581String labelText = " "; // Non-empty to reserve vertical space582int row = vmTable.getSelectedRow();583if (row >= 0) {584LocalVirtualMachine lvm = vmModel.vmAt(row);585if (!lvm.isManageable()) {586if (lvm.isAttachable()) {587labelText = Messages.MANAGEMENT_WILL_BE_ENABLED;588} else {589labelText = Messages.MANAGEMENT_NOT_ENABLED;590}591}592}593String colorStr =594String.format("%06x", hintTextColor.getRGB() & 0xFFFFFF);595localMessageLabel.setText("<html><font color=#" + colorStr + ">" + labelText);596}597// ----598599600// Refresh the list of managed VMs601public void refresh() {602if (vmModel != null) {603// Remember selection604LocalVirtualMachine selected = null;605int row = vmTable.getSelectedRow();606if (row >= 0) {607selected = vmModel.vmAt(row);608}609610vmModel.refresh();611612int selectRow = -1;613int n = vmModel.getRowCount();614if (selected != null) {615for (int i = 0; i < n; i++) {616LocalVirtualMachine lvm = vmModel.vmAt(i);617if (selected.vmid() == lvm.vmid() &&618selected.toString().equals(lvm.toString())) {619620selectRow = i;621break;622}623}624}625if (selectRow > -1) {626vmTable.setRowSelectionInterval(selectRow, selectRow);627} else {628vmTable.getSelectionModel().clearSelection();629}630631Dimension dim = vmTable.getPreferredSize();632633// Tricky. Reduce height by one to avoid double line at bottom,634// but that causes a scroll bar to appear, so remove it.635dim.height = Math.min(dim.height-1, 100);636localTableScrollPane.setVerticalScrollBarPolicy((dim.height < 100)637? JScrollPane.VERTICAL_SCROLLBAR_NEVER638: JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);639localTableScrollPane.getViewport().setMinimumSize(dim);640localTableScrollPane.getViewport().setPreferredSize(dim);641}642pack();643setLocationRelativeTo(jConsole);644}645646// Represents the list of managed VMs as a tabular data model.647private static class ManagedVmTableModel extends AbstractTableModel {648private static String[] columnNames = {649Messages.COLUMN_NAME,650Messages.COLUMN_PID,651};652653private List<LocalVirtualMachine> vmList;654655public int getColumnCount() {656return columnNames.length;657}658659public String getColumnName(int col) {660return columnNames[col];661}662663public synchronized int getRowCount() {664return vmList.size();665}666667public synchronized Object getValueAt(int row, int col) {668assert col >= 0 && col <= columnNames.length;669LocalVirtualMachine vm = vmList.get(row);670switch (col) {671case COL_NAME: return vm.displayName();672case COL_PID: return vm.vmid();673default: return null;674}675}676677public Class<?> getColumnClass(int column) {678switch (column) {679case COL_NAME: return String.class;680case COL_PID: return Integer.class;681default: return super.getColumnClass(column);682}683}684685public ManagedVmTableModel() {686refresh();687}688689690public synchronized LocalVirtualMachine vmAt(int pos) {691return vmList.get(pos);692}693694public synchronized void refresh() {695Map<Integer, LocalVirtualMachine> map =696LocalVirtualMachine.getAllVirtualMachines();697vmList = new ArrayList<LocalVirtualMachine>();698vmList.addAll(map.values());699700// data has changed701fireTableDataChanged();702}703}704705// A blank component that takes up as much space as the706// button part of a JRadioButton.707private static class Padder extends JPanel {708JRadioButton radioButton;709710Padder(JRadioButton radioButton) {711this.radioButton = radioButton;712713setAccessibleName(this, Messages.BLANK);714}715716public Dimension getPreferredSize() {717Rectangle r = getTextRectangle(radioButton);718int w = (r != null && r.x > 8) ? r.x : 22;719720return new Dimension(w, 0);721}722723private static Rectangle getTextRectangle(AbstractButton button) {724String text = button.getText();725Icon icon = (button.isEnabled()) ? button.getIcon() : button.getDisabledIcon();726727if (icon == null && button.getUI() instanceof BasicRadioButtonUI) {728icon = ((BasicRadioButtonUI)button.getUI()).getDefaultIcon();729}730731if ((icon == null) && (text == null)) {732return null;733}734735Rectangle paintIconR = new Rectangle();736Rectangle paintTextR = new Rectangle();737Rectangle paintViewR = new Rectangle();738Insets paintViewInsets = new Insets(0, 0, 0, 0);739740paintViewInsets = button.getInsets(paintViewInsets);741paintViewR.x = paintViewInsets.left;742paintViewR.y = paintViewInsets.top;743paintViewR.width = button.getWidth() - (paintViewInsets.left + paintViewInsets.right);744paintViewR.height = button.getHeight() - (paintViewInsets.top + paintViewInsets.bottom);745746Graphics g = button.getGraphics();747if (g == null) {748return null;749}750SwingUtilities.layoutCompoundLabel(button,751g.getFontMetrics(),752text,753icon,754button.getVerticalAlignment(),755button.getHorizontalAlignment(),756button.getVerticalTextPosition(),757button.getHorizontalTextPosition(),758paintViewR,759paintIconR,760paintTextR,761button.getIconTextGap());762763return paintTextR;764}765}766767}768769770