/*
 * Copyright 2004-2007 Sun Microsystems, Inc.  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.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package sun.tools.jconsole.inspector;

import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
import javax.swing.tree.*;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.FlowLayout;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.event.*;
import java.awt.Insets;
import java.awt.Dimension;
import java.util.*;
import java.io.*;

import java.lang.reflect.Array;

import javax.management.*;
import javax.management.openmbean.CompositeData;
import javax.management.openmbean.TabularData;

import sun.tools.jconsole.Resources;
import sun.tools.jconsole.MBeansTab;
import sun.tools.jconsole.Plotter;
import sun.tools.jconsole.JConsole;
import sun.tools.jconsole.ProxyClient.SnapshotMBeanServerConnection;

/*IMPORTANT :
  There is a deadlock issue there if we don't synchronize well loadAttributes,
  refresh attributes and empty table methods since a UI thread can call
  loadAttributes and at the same time a JMX notification can raise an
  emptyTable. Since there are synchronization in the JMX world it's
  COMPULSORY to not call the JMX world in synchronized blocks */
@SuppressWarnings("serial")
public class XMBeanAttributes extends XTable {
    private final static String[] columnNames =
    {Resources.getText("Name"),
     Resources.getText("Value")};

    private boolean editable = true;

    private XMBean mbean;
    private MBeanInfo mbeanInfo;
    private MBeanAttributeInfo[] attributesInfo;
    private HashMap<String, Object> attributes;
    private HashMap<String, Object> unavailableAttributes;
    private HashMap<String, Object> viewableAttributes;
    private WeakHashMap<XMBean, HashMap<String, ZoomedCell>> viewersCache =
            new WeakHashMap<XMBean, HashMap<String, ZoomedCell>>();
    private TableModelListener attributesListener;
    private MBeansTab mbeansTab;
    private XTable table;
    private TableCellEditor valueCellEditor = new ValueCellEditor();
    private int rowMinHeight = -1;
    private AttributesMouseListener mouseListener = new AttributesMouseListener();

    private static TableCellEditor editor =
            new Utils.ReadOnlyTableCellEditor(new JTextField());

    public XMBeanAttributes(MBeansTab mbeansTab) {
        super();
        this.mbeansTab = mbeansTab;
        ((DefaultTableModel)getModel()).setColumnIdentifiers(columnNames);
        getModel().addTableModelListener(attributesListener =
                                         new AttributesListener(this));
        getColumnModel().getColumn(NAME_COLUMN).setPreferredWidth(40);

        addMouseListener(mouseListener);
        getTableHeader().setReorderingAllowed(false);
        setColumnEditors();
        addKeyListener(new Utils.CopyKeyAdapter());
    }

    public synchronized Component prepareRenderer(TableCellRenderer renderer,
                                                  int row, int column) {
        //In case we have a repaint thread that is in the process of
        //repainting an obsolete table, just ignore the call.
        //It can happen when MBean selection is switched at a very quick rate
        if(row >= getRowCount())
            return null;
        else
            return super.prepareRenderer(renderer, row, column);
    }

    void updateRowHeight(Object obj, int row) {
        ZoomedCell cell = null;
        if(obj instanceof ZoomedCell) {
            cell = (ZoomedCell) obj;
            if(cell.isInited())
                setRowHeight(row, cell.getHeight());
            else
                if(rowMinHeight != - 1)
                    setRowHeight(row, rowMinHeight);
        } else
            if(rowMinHeight != - 1)
                setRowHeight(row, rowMinHeight);
    }

    public synchronized TableCellRenderer getCellRenderer(int row,
            int column) {
        //In case we have a repaint thread that is in the process of
        //repainting an obsolete table, just ignore the call.
        //It can happen when MBean selection is switched at a very quick rate
        if (row >= getRowCount()) {
            return null;
        } else {
            if (column == VALUE_COLUMN) {
                Object obj = getModel().getValueAt(row, column);
                if (obj instanceof ZoomedCell) {
                    ZoomedCell cell = (ZoomedCell) obj;
                    if (cell.isInited()) {
                        DefaultTableCellRenderer renderer =
                                (DefaultTableCellRenderer) cell.getRenderer();
                        renderer.setToolTipText(getToolTip(row,column));
                        return renderer;
                    }
                }
            }
            DefaultTableCellRenderer renderer = (DefaultTableCellRenderer)
                super.getCellRenderer(row, column);
            if (!isCellError(row, column)) {
                if (!(isColumnEditable(column) && isWritable(row) &&
                      Utils.isEditableType(getClassName(row)))) {
                    renderer.setForeground(getDefaultColor());
                }
            }
            return renderer;
        }
    }

    private void setColumnEditors() {
        TableColumnModel tcm = getColumnModel();
        for (int i = 0; i < columnNames.length; i++) {
            TableColumn tc = tcm.getColumn(i);
            if (isColumnEditable(i)) {
                tc.setCellEditor(valueCellEditor);
            } else {
                tc.setCellEditor(editor);
            }
        }
    }

    public void cancelCellEditing() {
        TableCellEditor editor = getCellEditor();
        if (editor != null) {
            editor.cancelCellEditing();
        }
    }

    public void stopCellEditing() {
        TableCellEditor editor = getCellEditor();
        if (editor != null) {
            editor.stopCellEditing();
        }
    }

    public final boolean editCellAt(int row, int column, EventObject e) {
        boolean retVal = super.editCellAt(row, column, e);
        if (retVal) {
            TableCellEditor editor =
                    getColumnModel().getColumn(column).getCellEditor();
            if (editor == valueCellEditor) {
                ((JComponent) editor).requestFocus();
            }
        }
        return retVal;
    }

    @Override
    public boolean isCellEditable(int row, int col) {
        // All the cells in non-editable columns are editable
        if (!isColumnEditable(col)) {
            return true;
        }
        // Maximized zoomed cells are editable
        Object obj = getModel().getValueAt(row, col);
        if (obj instanceof ZoomedCell) {
            ZoomedCell cell = (ZoomedCell) obj;
            return cell.isMaximized();
        }
        return true;
    }

    @Override
    public void setValueAt(Object value, int row, int column) {
        if (!isCellError(row, column) && isColumnEditable(column) &&
            isWritable(row) && Utils.isEditableType(getClassName(row))) {
            super.setValueAt(value, row, column);
        }
    }

    //Table methods

    public boolean isTableEditable() {
        return true;
    }

    public void setTableValue(Object value, int row) {
    }

    public boolean isColumnEditable(int column) {
        if (column < getColumnCount()) {
            return getColumnName(column).equals(Resources.getText("Value"));
        }
        else {
            return false;
        }
    }

    public String getClassName(int row) {
        int index = convertRowToIndex(row);
        if (index != -1) {
            return attributesInfo[index].getType();
        }
        else {
            return null;
        }
    }


    public String getValueName(int row) {
        int index = convertRowToIndex(row);
        if (index != -1) {
            return attributesInfo[index].getName();
        }
        else {
            return null;
        }
    }


    public Object getValue(int row) {
        return ((DefaultTableModel) getModel()).getValueAt(row, VALUE_COLUMN);
    }

    //tool tip only for editable column
    public String getToolTip(int row, int column) {
        if (isCellError(row, column)) {
            return (String) unavailableAttributes.get(getValueName(row));
        }
        if (isColumnEditable(column)) {
            Object value = getValue(row);
            String tip = null;
            if (value != null) {
                tip = value.toString();
                if(isAttributeViewable(row, VALUE_COLUMN))
                    tip = Resources.getText("Double click to expand/collapse")+
                        ". " + tip;
            }

            return tip;
        }

        if(column == NAME_COLUMN) {
            int index = convertRowToIndex(row);
            if (index != -1) {
                return attributesInfo[index].getDescription();
            }
        }
        return null;
    }

    public synchronized boolean isWritable(int row) {
        int index = convertRowToIndex(row);
        if (index != -1) {
            return (attributesInfo[index].isWritable());
        }
        else {
            return false;
        }
    }

    /**
     * Override JTable method in order to make any call to this method
     * atomic with TableModel elements.
     */
    public synchronized int getRowCount() {
        return super.getRowCount();
    }

    public synchronized boolean isReadable(int row) {
        int index = convertRowToIndex(row);
        if (index != -1) {
            return (attributesInfo[index].isReadable());
        }
        else {
            return false;
        }
    }

    public synchronized boolean isCellError(int row, int col) {
        return (isColumnEditable(col) &&
                (unavailableAttributes.containsKey(getValueName(row))));
    }

    public synchronized boolean isAttributeViewable(int row, int col) {
        boolean isViewable = false;
        if(col == VALUE_COLUMN) {
            Object obj = getModel().getValueAt(row, col);
            if(obj instanceof ZoomedCell)
                isViewable = true;
        }

        return isViewable;
    }

    public void loadAttributes(final XMBean mbean, MBeanInfo mbeanInfo) {
        // To avoid deadlock with events coming from the JMX side,
        // we retrieve all JMX stuff in a non synchronized block.

        if(mbean == null) return;

        final MBeanAttributeInfo[] attributesInfo = mbeanInfo.getAttributes();
        final HashMap<String, Object> attributes =
            new HashMap<String, Object>(attributesInfo.length);
        final HashMap<String, Object> unavailableAttributes =
            new HashMap<String, Object>(attributesInfo.length);
        final HashMap<String, Object> viewableAttributes =
            new HashMap<String, Object>(attributesInfo.length);
        AttributeList list = null;

        try {
            list = mbean.getAttributes(attributesInfo);
        }catch(Exception e) {
            list = new AttributeList();
            //Can't load all attributes, do it one after each other.
            for(int i = 0; i < attributesInfo.length; i++) {
                String name = null;
                try {
                    name = attributesInfo[i].getName();
                    Object value =
                        mbean.getAttribute(name);
                    list.add(new Attribute(name, value));
                }catch(Exception ex) {
                    if(attributesInfo[i].isReadable()) {
                        unavailableAttributes.put(name,
                                                  Utils.getActualException(ex).
                                                  toString());
                    }
                }
            }
        }
        try {
            int att_length = list.size();
            for (int i=0;i<att_length;i++) {
                Attribute attribute = (Attribute) list.get(i);
                if(isViewable(attribute)) {
                    viewableAttributes.put(attribute.getName(),
                                           attribute.getValue());
                }
                else
                    attributes.put(attribute.getName(),attribute.getValue());

            }
            // if not all attributes are accessible,
            // check them one after the other.
            if (att_length < attributesInfo.length) {
                for (int i=0;i<attributesInfo.length;i++) {
                    MBeanAttributeInfo attributeInfo = attributesInfo[i];
                    if (!attributes.containsKey(attributeInfo.getName()) &&
                        !viewableAttributes.containsKey(attributeInfo.
                                                        getName()) &&
                        !unavailableAttributes.containsKey(attributeInfo.
                                                           getName())) {
                        if (attributeInfo.isReadable()) {
                            // getAttributes didn't help resolving the
                            // exception.
                            // We must call it again to understand what
                            // went wrong.
                            try {
                                Object v =
                                    mbean.getAttribute(attributeInfo.
                                                       getName());
                                //What happens if now it is ok?
                                // Be pragmatic, add it to readable...
                                attributes.put(attributeInfo.getName(),
                                               v);
                            }catch(Exception e) {
                                //Put the exception that will be displayed
                                // in tooltip
                                unavailableAttributes.put(attributeInfo.
                                                          getName(),
                                                          Utils.
                                                          getActualException(e)
                                                          .toString());
                            }
                        }
                    }
                }
            }
        }
        catch(Exception e) {
            //sets all attributes unavailable except the writable ones
            for (int i=0;i<attributesInfo.length;i++) {
                MBeanAttributeInfo attributeInfo = attributesInfo[i];
                if (attributeInfo.isReadable()) {
                    unavailableAttributes.put(attributeInfo.getName(),
                                              Utils.getActualException(e).
                                              toString());
                }
            }
        }
        //end of retrieval

        //one update at a time
        synchronized(this) {

            this.mbean = mbean;
            this.mbeanInfo = mbeanInfo;
            this.attributesInfo = attributesInfo;
            this.attributes = attributes;
            this.unavailableAttributes = unavailableAttributes;
            this.viewableAttributes = viewableAttributes;

            EventQueue.invokeLater(new Runnable() {
                public void run() {
                    DefaultTableModel tableModel =
                            (DefaultTableModel) getModel();

                    // don't listen to these events
                    tableModel.removeTableModelListener(attributesListener);

                    // add attribute information
                    emptyTable();

                    addTableData(tableModel,
                                 mbean,
                                 attributesInfo,
                                 attributes,
                                 unavailableAttributes,
                                 viewableAttributes);

                    // update the model with the new data
                    tableModel.newDataAvailable(new TableModelEvent(tableModel));
                    // re-register for change events
                    tableModel.addTableModelListener(attributesListener);
                }
            });
        }
    }

    void collapse(String attributeName, final Component c) {
        final int row = getSelectedRow();
        Object obj = getModel().getValueAt(row, VALUE_COLUMN);
        if(obj instanceof ZoomedCell) {
            cancelCellEditing();
            ZoomedCell cell = (ZoomedCell) obj;
            cell.reset();
            setRowHeight(row,
                         cell.getHeight());
            editCellAt(row,
                       VALUE_COLUMN);
            invalidate();
            repaint();
        }
    }

    ZoomedCell updateZoomedCell(int row,
                                int col) {
        Object obj = getModel().getValueAt(row, VALUE_COLUMN);
        ZoomedCell cell = null;
        if(obj instanceof ZoomedCell) {
            cell = (ZoomedCell) obj;
            if(!cell.isInited()) {
                Object elem = cell.getValue();
                String attributeName =
                    (String) getModel().getValueAt(row,
                                                   NAME_COLUMN);
                Component comp = mbeansTab.getDataViewer().
                        createAttributeViewer(elem, mbean, attributeName, this);
                if(comp != null){
                    if(rowMinHeight == -1)
                        rowMinHeight = getRowHeight(row);

                    cell.init(super.getCellRenderer(row, col),
                              comp,
                              rowMinHeight);

                    mbeansTab.getDataViewer().registerForMouseEvent(
                            comp, mouseListener);
                } else
                    return cell;
            }

            cell.switchState();
            setRowHeight(row,
                         cell.getHeight());

            if(!cell.isMaximized()) {
                cancelCellEditing();
                //Back to simple editor.
                editCellAt(row,
                           VALUE_COLUMN);
            }

            invalidate();
            repaint();
        }
        return cell;
    }

     public void refreshAttributes() {
         MBeanServerConnection mbsc = mbeansTab.getMBeanServerConnection();
         if (mbsc instanceof SnapshotMBeanServerConnection) {
             ((SnapshotMBeanServerConnection) mbsc).flush();
         }
         stopCellEditing();
         loadAttributes(mbean, mbeanInfo);
     }


     public void emptyTable() {
         synchronized(this) {
             ((DefaultTableModel) getModel()).
                 removeTableModelListener(attributesListener);
             super.emptyTable();
         }
     }

    private boolean isViewable(Attribute attribute) {
        Object data = attribute.getValue();
        return XDataViewer.isViewableValue(data);

    }

    synchronized void removeAttributes() {
        if (attributes != null) {
            attributes.clear();
        }
        if (unavailableAttributes != null) {
            unavailableAttributes.clear();
        }
        if (viewableAttributes != null) {
            viewableAttributes.clear();
        }
        mbean = null;
    }

    private ZoomedCell getZoomedCell(XMBean mbean, String attribute, Object value) {
        synchronized (viewersCache) {
            HashMap<String, ZoomedCell> viewers;
            if (viewersCache.containsKey(mbean)) {
                viewers = viewersCache.get(mbean);
            } else {
                viewers = new HashMap<String, ZoomedCell>();
            }
            ZoomedCell cell;
            if (viewers.containsKey(attribute)) {
                cell = viewers.get(attribute);
                cell.setValue(value);
                if (cell.isMaximized() && cell.getType() != XDataViewer.NUMERIC) {
                    // Plotters are the only viewers with auto update capabilities.
                    // Other viewers need to be updated manually.
                    Component comp =
                        mbeansTab.getDataViewer().createAttributeViewer(
                            value, mbean, attribute, XMBeanAttributes.this);
                    cell.init(cell.getMinRenderer(), comp, cell.getMinHeight());
                    mbeansTab.getDataViewer().registerForMouseEvent(comp, mouseListener);
                }
            } else {
                cell = new ZoomedCell(value);
                viewers.put(attribute, cell);
            }
            viewersCache.put(mbean, viewers);
            return cell;
        }
    }

    //will be called in a synchronzed block
    protected void addTableData(DefaultTableModel tableModel,
                                XMBean mbean,
                                MBeanAttributeInfo[] attributesInfo,
                                HashMap<String, Object> attributes,
                                HashMap<String, Object> unavailableAttributes,
                                HashMap<String, Object> viewableAttributes) {

        Object rowData[] = new Object[2];
        int col1Width = 0;
        int col2Width = 0;
        for (int i = 0; i < attributesInfo.length; i++) {
            rowData[0] = (attributesInfo[i].getName());
            if (unavailableAttributes.containsKey(rowData[0])) {
                rowData[1] = Resources.getText("Unavailable");
            } else if (viewableAttributes.containsKey(rowData[0])) {
                rowData[1] = viewableAttributes.get(rowData[0]);
                if (!attributesInfo[i].isWritable() ||
                    !Utils.isEditableType(attributesInfo[i].getType())) {
                    rowData[1] = getZoomedCell(mbean, (String) rowData[0], rowData[1]);
                }
            } else {
                rowData[1] = attributes.get(rowData[0]);
            }

            tableModel.addRow(rowData);

            //Update column width
            //
            String str = null;
            if(rowData[0] != null) {
                str = rowData[0].toString();
                if(str.length() > col1Width)
                    col1Width = str.length();
            }
            if(rowData[1] != null) {
                str = rowData[1].toString();
                if(str.length() > col2Width)
                    col2Width = str.length();
            }
        }
        updateColumnWidth(col1Width, col2Width);
    }

    private void updateColumnWidth(int col1Width, int col2Width) {
        TableColumnModel colModel = getColumnModel();

        //Get the column at index pColumn, and set its preferred width.
        col1Width = col1Width * 7;
        col2Width = col2Width * 7;
        if(col1Width + col2Width <
           (int) getPreferredScrollableViewportSize().getWidth())
            col2Width = (int) getPreferredScrollableViewportSize().getWidth()
                - col1Width;

        colModel.getColumn(NAME_COLUMN).setPreferredWidth(50);
    }

    class AttributesMouseListener extends MouseAdapter {

        public void mousePressed(MouseEvent e) {
            if(e.getButton() == MouseEvent.BUTTON1) {
                if(e.getClickCount() >= 2) {

                    int row = XMBeanAttributes.this.getSelectedRow();
                    int col = XMBeanAttributes.this.getSelectedColumn();
                    if(col != VALUE_COLUMN) return;
                    if(col == -1 || row == -1) return;

                    XMBeanAttributes.this.updateZoomedCell(row, col);
                }
            }
        }
    }

    class ValueCellEditor extends XTextFieldEditor {
        // implements javax.swing.table.TableCellEditor
        public Component getTableCellEditorComponent(JTable table,
                                                     Object value,
                                                     boolean isSelected,
                                                     int row,
                                                     int column) {
            Object val = value;
            if(column == VALUE_COLUMN) {
                Object obj = getModel().getValueAt(row,
                                                   column);
                if(obj instanceof ZoomedCell) {
                    ZoomedCell cell = (ZoomedCell) obj;
                    if(cell.getRenderer() instanceof MaximizedCellRenderer) {
                        MaximizedCellRenderer zr =
                            (MaximizedCellRenderer) cell.getRenderer();
                        return zr.getComponent();
                    }
                } else {
                    Component comp = super.getTableCellEditorComponent(
                            table, val, isSelected, row, column);
                    if (isCellError(row, column) ||
                        !isWritable(row) ||
                        !Utils.isEditableType(getClassName(row))) {
                        textField.setEditable(false);
                    }
                    return comp;
                }
            }
            return super.getTableCellEditorComponent(table,
                                                     val,
                                                     isSelected,
                                                     row,
                                                     column);
        }
        @Override
        public boolean stopCellEditing() {
            int editingRow = getEditingRow();
            int editingColumn = getEditingColumn();
            if (editingColumn == VALUE_COLUMN) {
                Object obj = getModel().getValueAt(editingRow, editingColumn);
                if (obj instanceof ZoomedCell) {
                    ZoomedCell cell = (ZoomedCell) obj;
                    if (cell.isMaximized()) {
                        this.cancelCellEditing();
                        return true;
                    }
                }
            }
            return super.stopCellEditing();
        }
    }

    class MaximizedCellRenderer extends  DefaultTableCellRenderer {
        Component comp;
        MaximizedCellRenderer(Component comp) {
            this.comp = comp;
            Dimension d = comp.getPreferredSize();
            if (d.getHeight() > 200) {
                comp.setPreferredSize(new Dimension((int) d.getWidth(), 200));
            }
        }
        public Component getTableCellRendererComponent(JTable table,
                                                       Object value,
                                                       boolean isSelected,
                                                       boolean hasFocus,
                                                       int row,
                                                       int column) {
            return comp;
        }
        public Component getComponent() {
            return comp;
        }
    }

    class ZoomedCell {
        TableCellRenderer minRenderer;
        MaximizedCellRenderer maxRenderer;
        int minHeight;
        boolean minimized = true;
        boolean init = false;
        int type;
        Object value;
        ZoomedCell(Object value) {
            type = XDataViewer.getViewerType(value);
            this.value = value;
        }

        boolean isInited() {
            return init;
        }

        Object getValue() {
            return value;
        }

        void setValue(Object value) {
            this.value = value;
        }

        void init(TableCellRenderer minRenderer,
                  Component maxComponent,
                  int minHeight) {
            this.minRenderer = minRenderer;
            this.maxRenderer = new MaximizedCellRenderer(maxComponent);

            this.minHeight = minHeight;
            init = true;
        }

        int getType() {
            return type;
        }

        void reset() {
            init = false;
            minimized = true;
        }

        void switchState() {
            minimized = !minimized;
        }
        boolean isMaximized() {
            return !minimized;
        }
        void minimize() {
            minimized = true;
        }

        void maximize() {
            minimized = false;
        }

        int getHeight() {
            if(minimized) return minHeight;
            else
                return (int) maxRenderer.getComponent().
                    getPreferredSize().getHeight() ;
        }

        int getMinHeight() {
            return minHeight;
        }

        public String toString() {

            if(value == null) return null;

            if(value.getClass().isArray()) {
                String name =
                    Utils.getArrayClassName(value.getClass().getName());
                int length = Array.getLength(value);
                return name + "[" + length +"]";
            }

            if(value instanceof CompositeData ||
               value instanceof TabularData)
                return value.getClass().getName();

            return value.toString();
        }

        TableCellRenderer getRenderer() {
            if(minimized) return minRenderer;
            else return maxRenderer;
        }

        TableCellRenderer getMinRenderer() {
            return minRenderer;
        }
    }

    class AttributesListener implements  TableModelListener {

        private Component component;

        public AttributesListener(Component component) {
            this.component = component;
        }

        public void tableChanged(final TableModelEvent e) {
            final TableModel model = (TableModel)e.getSource();
            // only post changes to the draggable column
            if (isColumnEditable(e.getColumn())) {
                mbeansTab.workerAdd(new Runnable() {
                        public void run() {
                            try {
                                Object tableValue =
                                    model.getValueAt(e.getFirstRow(),
                                                     e.getColumn());
                                // if it's a String, try construct new value
                                // using the defined type.
                                if (tableValue instanceof String) {
                                    tableValue =
                                        Utils.createObjectFromString(getClassName(e.getFirstRow()), // type
                                                                     (String)tableValue);// value
                                }
                                String attributeName =
                                    getValueName(e.getFirstRow());
                                Attribute attribute =
                                    new Attribute(attributeName,tableValue);
                                mbean.setAttribute(attribute);
                            }
                            catch (Throwable ex) {
                                if (JConsole.isDebug()) {
                                    ex.printStackTrace();
                                }
                                ex = Utils.getActualException(ex);

                                String message = (ex.getMessage() != null) ? ex.getMessage() : ex.toString();
                                EventQueue.invokeLater(new ThreadDialog(component,
                                                                        message+"\n",
                                                                        Resources.getText("Problem setting attribute"),
                                                                        JOptionPane.ERROR_MESSAGE));
                            }
                            refreshAttributes();
                        }
                    });
            }
        }
    }
}
