feat(jdk8): move files to new folder to avoid resources compiled.

This commit is contained in:
2025-09-07 15:25:52 +08:00
parent 3f0047bf6f
commit 8c35cfb1c0
17415 changed files with 217 additions and 213 deletions

View File

@@ -0,0 +1,50 @@
/*
* Copyright (c) 2004, 2006, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.jconsole.inspector;
import java.awt.Image;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import sun.tools.jconsole.JConsole;
public class IconManager {
public static Icon MBEAN =
getSmallIcon(getImage("mbean.gif"));
public static Icon MBEANSERVERDELEGATE =
getSmallIcon(getImage("mbeanserverdelegate.gif"));
public static Icon DEFAULT_XOBJECT =
getSmallIcon(getImage("xobject.gif"));
private static ImageIcon getImage(String img) {
return new ImageIcon(JConsole.class.getResource("resources/" + img));
}
private static ImageIcon getSmallIcon(ImageIcon icon) {
return new ImageIcon(
icon.getImage().getScaledInstance(16, 16, Image.SCALE_SMOOTH));
}
}

View File

@@ -0,0 +1,112 @@
/*
* Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.jconsole.inspector;
import java.awt.*;
import javax.swing.*;
import javax.management.*;
@SuppressWarnings("serial")
public class OperationEntry extends JPanel {
private MBeanOperationInfo operation;
private JComboBox sigs;
private XTextField inputs[];
public OperationEntry (MBeanOperationInfo operation,
boolean isCallable,
JButton button,
XOperations xoperations) {
super(new BorderLayout());
this.operation = operation;
setLayout(new FlowLayout(FlowLayout.LEFT));
setPanel(isCallable, button, xoperations);
}
private void setPanel(boolean isCallable,
JButton button,
XOperations xoperations) {
try {
MBeanParameterInfo params[] = operation.getSignature();
add(new JLabel("(",JLabel.CENTER));
inputs = new XTextField[params.length];
for (int i = 0; i < params.length; i++) {
if(params[i].getName() != null) {
JLabel name =
new JLabel(params[i].getName(), JLabel.CENTER);
name.setToolTipText(params[i].getDescription());
add(name);
}
String defaultTextValue =
Utils.getDefaultValue(params[i].getType());
int fieldWidth = defaultTextValue.length();
if (fieldWidth > 15) fieldWidth = 15;
else
if (fieldWidth < 10) fieldWidth = 10;
add(inputs[i] =
new XTextField(Utils.getReadableClassName(defaultTextValue),
Utils.getClass(params[i].getType()),
fieldWidth,
isCallable,
button,
xoperations));
inputs[i].setHorizontalAlignment(SwingConstants.CENTER);
if (i < params.length-1)
add(new JLabel(",",JLabel.CENTER));
}
add(new JLabel(")",JLabel.CENTER));
validate();
doLayout();
}
catch (Exception e) {
System.out.println("Error setting Operation panel :"+
e.getMessage());
}
}
public String[] getSignature() {
MBeanParameterInfo params[] = operation.getSignature();
String result[] = new String[params.length];
for (int i = 0; i < params.length; i++) {
result[i] = params[i].getType();
}
return result;
}
public Object[] getParameters() throws Exception {
MBeanParameterInfo params[] = operation.getSignature();
String signature[] = new String[params.length];
for (int i = 0; i < params.length; i++)
signature[i] = params[i].getType();
return Utils.getParameters(inputs,signature);
}
public String getReturnType() {
return operation.getReturnType();
}
}

View File

@@ -0,0 +1,292 @@
/*
* Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.jconsole.inspector;
// Imports for picking up mouse events from the JTable.
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Vector;
import javax.swing.JTable;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumnModel;
import sun.tools.jconsole.JConsole;
@SuppressWarnings("serial")
public class TableSorter extends DefaultTableModel implements MouseListener {
private boolean ascending = true;
private TableColumnModel columnModel;
private JTable tableView;
private Vector<TableModelListener> evtListenerList;
private int sortColumn = 0;
private int[] invertedIndex;
public TableSorter() {
super();
evtListenerList = new Vector<TableModelListener>();
}
public TableSorter(Object[] columnNames, int numRows) {
super(columnNames,numRows);
evtListenerList = new Vector<TableModelListener>();
}
@Override
public void newDataAvailable(TableModelEvent e) {
super.newDataAvailable(e);
invertedIndex = new int[getRowCount()];
for (int i = 0; i < invertedIndex.length; i++) {
invertedIndex[i] = i;
}
sort(this.sortColumn, this.ascending);
}
@Override
public void addTableModelListener(TableModelListener l) {
evtListenerList.add(l);
super.addTableModelListener(l);
}
@Override
public void removeTableModelListener(TableModelListener l) {
evtListenerList.remove(l);
super.removeTableModelListener(l);
}
private void removeListeners() {
for(TableModelListener tnl : evtListenerList)
super.removeTableModelListener(tnl);
}
private void restoreListeners() {
for(TableModelListener tnl : evtListenerList)
super.addTableModelListener(tnl);
}
@SuppressWarnings("unchecked")
private int compare(Object o1, Object o2) {
// take care of the case where both o1 & o2 are null. Needed to keep
// the method symmetric. Without this quickSort gives surprising results.
if (o1 == o2)
return 0;
if (o1==null)
return 1;
if (o2==null)
return -1;
//two object of the same class and that are comparable
else if ((o1.getClass().equals(o2.getClass())) &&
(o1 instanceof Comparable)) {
return (((Comparable) o1).compareTo(o2));
}
else {
return o1.toString().compareTo(o2.toString());
}
}
private void sort(int column, boolean isAscending) {
final XMBeanAttributes attrs =
(tableView instanceof XMBeanAttributes)
?(XMBeanAttributes) tableView
:null;
// We cannot sort rows when a cell is being
// edited - so we're going to cancel cell editing here if needed.
// This might happen when the user is editing a row, and clicks on
// another row without validating. In that case there are two events
// that compete: one is the validation of the value that was previously
// edited, the other is the mouse click that opens the new editor.
//
// When we reach here the previous value is already validated, and the
// old editor is closed, but the new editor might have opened.
// It's this new editor that wil be cancelled here, if needed.
//
if (attrs != null && attrs.isEditing())
attrs.cancelCellEditing();
// remove registered listeners
removeListeners();
// do the sort
if (JConsole.isDebug()) {
System.err.println("sorting table against column="+column
+" ascending="+isAscending);
}
quickSort(0,getRowCount()-1,column,isAscending);
// restore registered listeners
restoreListeners();
// update row heights in XMBeanAttributes (required by expandable cells)
if (attrs != null) {
for (int i = 0; i < getRowCount(); i++) {
Vector data = (Vector) dataVector.elementAt(i);
attrs.updateRowHeight(data.elementAt(1), i);
}
}
}
private boolean compareS(Object s1, Object s2, boolean isAscending) {
if (isAscending)
return (compare(s1,s2) > 0);
else
return (compare(s1,s2) < 0);
}
private boolean compareG(Object s1, Object s2, boolean isAscending) {
if (isAscending)
return (compare(s1,s2) < 0);
else
return (compare(s1,s2) > 0);
}
private void quickSort(int lo0,int hi0, int key, boolean isAscending) {
int lo = lo0;
int hi = hi0;
Object mid;
if ( hi0 > lo0)
{
mid = getValueAt( ( lo0 + hi0 ) / 2 , key);
while( lo <= hi )
{
/* find the first element that is greater than
* or equal to the partition element starting
* from the left Index.
*/
while( ( lo < hi0 ) &&
( compareS(mid,getValueAt(lo,key), isAscending) ))
++lo;
/* find an element that is smaller than or equal to
* the partition element starting from the right Index.
*/
while( ( hi > lo0 ) &&
( compareG(mid,getValueAt(hi,key), isAscending) ))
--hi;
// if the indexes have not crossed, swap
if( lo <= hi )
{
swap(lo, hi, key);
++lo;
--hi;
}
}
/* If the right index has not reached the
* left side of array
* must now sort the left partition.
*/
if( lo0 < hi )
quickSort(lo0, hi , key, isAscending);
/* If the left index has not reached the right
* side of array
* must now sort the right partition.
*/
if( lo <= hi0 )
quickSort(lo, hi0 , key, isAscending);
}
}
private Vector getRow(int row) {
return (Vector) dataVector.elementAt(row);
}
@SuppressWarnings("unchecked")
private void setRow(Vector data, int row) {
dataVector.setElementAt(data,row);
}
private void swap(int i, int j, int column) {
Vector data = getRow(i);
setRow(getRow(j),i);
setRow(data,j);
int a = invertedIndex[i];
invertedIndex[i] = invertedIndex[j];
invertedIndex[j] = a;
}
public void sortByColumn(int column) {
sortByColumn(column, !ascending);
}
public void sortByColumn(int column, boolean ascending) {
this.ascending = ascending;
this.sortColumn = column;
sort(column,ascending);
}
public int getIndexOfRow(int row) {
return invertedIndex[row];
}
// Add a mouse listener to the Table to trigger a table sort
// when a column heading is clicked in the JTable.
public void addMouseListenerToHeaderInTable(JTable table) {
tableView = table;
columnModel = tableView.getColumnModel();
JTableHeader th = tableView.getTableHeader();
th.addMouseListener(this);
}
public void mouseClicked(MouseEvent e) {
int viewColumn = columnModel.getColumnIndexAtX(e.getX());
int column = tableView.convertColumnIndexToModel(viewColumn);
if (e.getClickCount() == 1 && column != -1) {
if (tableView instanceof XTable) {
XTable attrs = (XTable) tableView;
// inform the table view that the rows are going to be sorted
// against the values in a given column. This gives the
// chance to the table view to close its editor - if needed.
//
attrs.sortRequested(column);
}
tableView.invalidate();
sortByColumn(column);
tableView.validate();
tableView.repaint();
}
}
public void mousePressed(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.jconsole.inspector;
// java import
import java.awt.*;
import javax.swing.*;
//
public class ThreadDialog implements Runnable {
Component parentComponent;
Object message;
String title;
int messageType;
public ThreadDialog(Component parentComponent,
Object message,
String title,
int messageType) {
this.parentComponent = parentComponent;
this.message = message;
this.title = title;
this.messageType = messageType;
}
public void run() {
JOptionPane pane = new JOptionPane(message, messageType);
JDialog dialog = pane.createDialog(parentComponent, title);
dialog.setResizable(true);
dialog.setVisible(true);
}
}

View File

@@ -0,0 +1,462 @@
/*
* Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.jconsole.inspector;
import java.awt.event.*;
import java.lang.reflect.*;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
import java.util.concurrent.ExecutionException;
import javax.management.*;
import javax.management.openmbean.*;
import javax.swing.*;
import javax.swing.text.*;
public class Utils {
private Utils() {
}
private static Set<Integer> tableNavigationKeys =
new HashSet<Integer>(Arrays.asList(new Integer[]{
KeyEvent.VK_TAB, KeyEvent.VK_ENTER,
KeyEvent.VK_HOME, KeyEvent.VK_END,
KeyEvent.VK_LEFT, KeyEvent.VK_RIGHT,
KeyEvent.VK_UP, KeyEvent.VK_DOWN,
KeyEvent.VK_PAGE_UP, KeyEvent.VK_PAGE_DOWN
}));
private static final Set<Class<?>> primitiveWrappers =
new HashSet<Class<?>>(Arrays.asList(new Class<?>[]{
Byte.class, Short.class, Integer.class, Long.class,
Float.class, Double.class, Character.class, Boolean.class
}));
private static final Set<Class<?>> primitives = new HashSet<Class<?>>();
private static final Map<String, Class<?>> primitiveMap =
new HashMap<String, Class<?>>();
private static final Map<String, Class<?>> primitiveToWrapper =
new HashMap<String, Class<?>>();
private static final Set<String> editableTypes = new HashSet<String>();
private static final Set<Class<?>> extraEditableClasses =
new HashSet<Class<?>>(Arrays.asList(new Class<?>[]{
BigDecimal.class, BigInteger.class, Number.class,
String.class, ObjectName.class
}));
private static final Set<String> numericalTypes = new HashSet<String>();
private static final Set<String> extraNumericalTypes =
new HashSet<String>(Arrays.asList(new String[]{
BigDecimal.class.getName(), BigInteger.class.getName(),
Number.class.getName()
}));
private static final Set<String> booleanTypes =
new HashSet<String>(Arrays.asList(new String[]{
Boolean.TYPE.getName(), Boolean.class.getName()
}));
static {
// compute primitives/primitiveMap/primitiveToWrapper
for (Class<?> c : primitiveWrappers) {
try {
Field f = c.getField("TYPE");
Class<?> p = (Class<?>) f.get(null);
primitives.add(p);
primitiveMap.put(p.getName(), p);
primitiveToWrapper.put(p.getName(), c);
} catch (Exception e) {
throw new AssertionError(e);
}
}
// compute editableTypes
for (Class<?> c : primitives) {
editableTypes.add(c.getName());
}
for (Class<?> c : primitiveWrappers) {
editableTypes.add(c.getName());
}
for (Class<?> c : extraEditableClasses) {
editableTypes.add(c.getName());
}
// compute numericalTypes
for (Class<?> c : primitives) {
String name = c.getName();
if (!name.equals(Boolean.TYPE.getName())) {
numericalTypes.add(name);
}
}
for (Class<?> c : primitiveWrappers) {
String name = c.getName();
if (!name.equals(Boolean.class.getName())) {
numericalTypes.add(name);
}
}
}
/**
* This method returns the class matching the name className.
* It's used to cater for the primitive types.
*/
public static Class<?> getClass(String className)
throws ClassNotFoundException {
Class<?> c;
if ((c = primitiveMap.get(className)) != null) {
return c;
}
return Class.forName(className);
}
/**
* Check if the given collection is a uniform collection of the given type.
*/
public static boolean isUniformCollection(Collection<?> c, Class<?> e) {
if (e == null) {
throw new IllegalArgumentException("Null reference type");
}
if (c == null) {
throw new IllegalArgumentException("Null collection");
}
if (c.isEmpty()) {
return false;
}
for (Object o : c) {
if (o == null || !e.isAssignableFrom(o.getClass())) {
return false;
}
}
return true;
}
/**
* Check if the given element denotes a supported array-friendly data
* structure, i.e. a data structure jconsole can render as an array.
*/
public static boolean canBeRenderedAsArray(Object elem) {
if (isSupportedArray(elem)) {
return true;
}
if (elem instanceof Collection) {
Collection<?> c = (Collection<?>) elem;
if (c.isEmpty()) {
// Empty collections of any Java type are not handled as arrays
//
return false;
} else {
// - Collections of CompositeData/TabularData are not handled
// as arrays
// - Collections of other Java types are handled as arrays
//
return !isUniformCollection(c, CompositeData.class) &&
!isUniformCollection(c, TabularData.class);
}
}
if (elem instanceof Map) {
return !(elem instanceof TabularData);
}
return false;
}
/**
* Check if the given element is an array.
*
* Multidimensional arrays are not supported.
*
* Non-empty 1-dimensional arrays of CompositeData
* and TabularData are not handled as arrays but as
* tabular data.
*/
public static boolean isSupportedArray(Object elem) {
if (elem == null || !elem.getClass().isArray()) {
return false;
}
Class<?> ct = elem.getClass().getComponentType();
if (ct.isArray()) {
return false;
}
if (Array.getLength(elem) > 0 &&
(CompositeData.class.isAssignableFrom(ct) ||
TabularData.class.isAssignableFrom(ct))) {
return false;
}
return true;
}
/**
* This method provides a readable classname if it's an array,
* i.e. either the classname of the component type for arrays
* of java reference types or the name of the primitive type
* for arrays of java primitive types. Otherwise, it returns null.
*/
public static String getArrayClassName(String name) {
String className = null;
if (name.startsWith("[")) {
int index = name.lastIndexOf("[");
className = name.substring(index, name.length());
if (className.startsWith("[L")) {
className = className.substring(2, className.length() - 1);
} else {
try {
Class<?> c = Class.forName(className);
className = c.getComponentType().getName();
} catch (ClassNotFoundException e) {
// Should not happen
throw new IllegalArgumentException(
"Bad class name " + name, e);
}
}
}
return className;
}
/**
* This methods provides a readable classname. If the supplied name
* parameter denotes an array this method returns either the classname
* of the component type for arrays of java reference types or the name
* of the primitive type for arrays of java primitive types followed by
* n-times "[]" where 'n' denotes the arity of the array. Otherwise, if
* the supplied name doesn't denote an array it returns the same classname.
*/
public static String getReadableClassName(String name) {
String className = getArrayClassName(name);
if (className == null) {
return name;
}
int index = name.lastIndexOf("[");
StringBuilder brackets = new StringBuilder(className);
for (int i = 0; i <= index; i++) {
brackets.append("[]");
}
return brackets.toString();
}
/**
* This method tells whether the type is editable
* (means can be created with a String or not)
*/
public static boolean isEditableType(String type) {
return editableTypes.contains(type);
}
/**
* This method inserts a default value for the standard java types,
* else it inserts the text name of the expected class type.
* It acts to give a clue as to the input type.
*/
public static String getDefaultValue(String type) {
if (numericalTypes.contains(type) ||
extraNumericalTypes.contains(type)) {
return "0";
}
if (booleanTypes.contains(type)) {
return "true";
}
type = getReadableClassName(type);
int i = type.lastIndexOf('.');
if (i > 0) {
return type.substring(i + 1, type.length());
} else {
return type;
}
}
/**
* Try to create a Java object using a one-string-param constructor.
*/
public static Object newStringConstructor(String type, String param)
throws Exception {
Constructor<?> c = Utils.getClass(type).getConstructor(String.class);
try {
return c.newInstance(param);
} catch (InvocationTargetException e) {
Throwable t = e.getTargetException();
if (t instanceof Exception) {
throw (Exception) t;
} else {
throw e;
}
}
}
/**
* Try to convert a string value into a numerical value.
*/
private static Number createNumberFromStringValue(String value)
throws NumberFormatException {
final String suffix = value.substring(value.length() - 1);
if ("L".equalsIgnoreCase(suffix)) {
return Long.valueOf(value.substring(0, value.length() - 1));
}
if ("F".equalsIgnoreCase(suffix)) {
return Float.valueOf(value.substring(0, value.length() - 1));
}
if ("D".equalsIgnoreCase(suffix)) {
return Double.valueOf(value.substring(0, value.length() - 1));
}
try {
return Integer.valueOf(value);
} catch (NumberFormatException e) {
// OK: Ignore exception...
}
try {
return Long.valueOf(value);
} catch (NumberFormatException e1) {
// OK: Ignore exception...
}
try {
return Double.valueOf(value);
} catch (NumberFormatException e2) {
// OK: Ignore exception...
}
throw new NumberFormatException("Cannot convert string value '" +
value + "' into a numerical value");
}
/**
* This method attempts to create an object of the given "type"
* using the "value" parameter.
* e.g. calling createObjectFromString("java.lang.Integer", "10")
* will return an Integer object initialized to 10.
*/
public static Object createObjectFromString(String type, String value)
throws Exception {
Object result;
if (primitiveToWrapper.containsKey(type)) {
if (type.equals(Character.TYPE.getName())) {
result = new Character(value.charAt(0));
} else {
result = newStringConstructor(
((Class<?>) primitiveToWrapper.get(type)).getName(),
value);
}
} else if (type.equals(Character.class.getName())) {
result = new Character(value.charAt(0));
} else if (Number.class.isAssignableFrom(Utils.getClass(type))) {
result = createNumberFromStringValue(value);
} else if (value == null || value.equals("null")) {
// hack for null value
result = null;
} else {
// try to create a Java object using
// the one-string-param constructor
result = newStringConstructor(type, value);
}
return result;
}
/**
* This method is responsible for converting the inputs given by the user
* into a useful object array for passing into a parameter array.
*/
public static Object[] getParameters(XTextField[] inputs, String[] params)
throws Exception {
Object result[] = new Object[inputs.length];
Object userInput;
for (int i = 0; i < inputs.length; i++) {
userInput = inputs[i].getValue();
// if it's already a complex object, use the value
// else try to instantiate with string constructor
if (userInput instanceof XObject) {
result[i] = ((XObject) userInput).getObject();
} else {
result[i] = createObjectFromString(params[i].toString(),
(String) userInput);
}
}
return result;
}
/**
* If the exception is wrapped, unwrap it.
*/
public static Throwable getActualException(Throwable e) {
if (e instanceof ExecutionException) {
e = e.getCause();
}
if (e instanceof MBeanException ||
e instanceof RuntimeMBeanException ||
e instanceof RuntimeOperationsException ||
e instanceof ReflectionException) {
Throwable t = e.getCause();
if (t != null) {
return t;
}
}
return e;
}
@SuppressWarnings("serial")
public static class ReadOnlyTableCellEditor
extends DefaultCellEditor {
public ReadOnlyTableCellEditor(JTextField tf) {
super(tf);
tf.addFocusListener(new Utils.EditFocusAdapter(this));
tf.addKeyListener(new Utils.CopyKeyAdapter());
}
}
public static class EditFocusAdapter extends FocusAdapter {
private CellEditor editor;
public EditFocusAdapter(CellEditor editor) {
this.editor = editor;
}
@Override
public void focusLost(FocusEvent e) {
editor.stopCellEditing();
}
}
public static class CopyKeyAdapter extends KeyAdapter {
private static final String defaultEditorKitCopyActionName =
DefaultEditorKit.copyAction;
private static final String transferHandlerCopyActionName =
(String) TransferHandler.getCopyAction().getValue(Action.NAME);
@Override
public void keyPressed(KeyEvent e) {
// Accept "copy" key strokes
KeyStroke ks = KeyStroke.getKeyStroke(
e.getKeyCode(), e.getModifiers());
JComponent comp = (JComponent) e.getSource();
for (int i = 0; i < 3; i++) {
InputMap im = comp.getInputMap(i);
Object key = im.get(ks);
if (defaultEditorKitCopyActionName.equals(key) ||
transferHandlerCopyActionName.equals(key)) {
return;
}
}
// Accept JTable navigation key strokes
if (!tableNavigationKeys.contains(e.getKeyCode())) {
e.consume();
}
}
@Override
public void keyTyped(KeyEvent e) {
e.consume();
}
}
}

View File

@@ -0,0 +1,113 @@
/*
* Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.jconsole.inspector;
import java.awt.Color;
import java.awt.Component;
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Map;
import javax.swing.JEditorPane;
import javax.swing.JScrollPane;
class XArrayDataViewer {
private XArrayDataViewer() {}
public static boolean isViewableValue(Object value) {
return Utils.canBeRenderedAsArray(value);
}
public static Component loadArray(Object value) {
Component comp = null;
if (isViewableValue(value)) {
Object[] arr;
if (value instanceof Collection) {
arr = ((Collection<?>) value).toArray();
} else if (value instanceof Map) {
arr = ((Map<?,?>) value).entrySet().toArray();
} else if (value instanceof Object[]) {
arr = (Object[]) value;
} else {
int length = Array.getLength(value);
arr = new Object[length];
for (int i = 0; i < length; i++) {
arr[i] = Array.get(value, i);
}
}
JEditorPane arrayEditor = new JEditorPane();
arrayEditor.setContentType("text/html");
arrayEditor.setEditable(false);
Color evenRowColor = arrayEditor.getBackground();
int red = evenRowColor.getRed();
int green = evenRowColor.getGreen();
int blue = evenRowColor.getBlue();
String evenRowColorStr =
"rgb(" + red + "," + green + "," + blue + ")";
Color oddRowColor = new Color(
red < 20 ? red + 20 : red - 20,
green < 20 ? green + 20 : green - 20,
blue < 20 ? blue + 20 : blue - 20);
String oddRowColorStr =
"rgb(" + oddRowColor.getRed() + "," +
oddRowColor.getGreen() + "," +
oddRowColor.getBlue() + ")";
Color foreground = arrayEditor.getForeground();
String textColor = String.format("%06x",
foreground.getRGB() & 0xFFFFFF);
StringBuilder sb = new StringBuilder();
sb.append("<html><body text=#"+textColor+"><table width=\"100%\">");
for (int i = 0; i < arr.length; i++) {
if (i % 2 == 0) {
sb.append("<tr style=\"background-color: " +
evenRowColorStr + "\"><td><pre>" +
(arr[i] == null ?
arr[i] : htmlize(arr[i].toString())) +
"</pre></td></tr>");
} else {
sb.append("<tr style=\"background-color: " +
oddRowColorStr + "\"><td><pre>" +
(arr[i] == null ?
arr[i] : htmlize(arr[i].toString())) +
"</pre></td></tr>");
}
}
if (arr.length == 0) {
sb.append("<tr style=\"background-color: " +
evenRowColorStr + "\"><td></td></tr>");
}
sb.append("</table></body></html>");
arrayEditor.setText(sb.toString());
JScrollPane scrollp = new JScrollPane(arrayEditor);
comp = scrollp;
}
return comp;
}
private static String htmlize(String value) {
return value.replace("&", "&amp;").replace("<", "&lt;");
}
}

View File

@@ -0,0 +1,148 @@
/*
* Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.jconsole.inspector;
import javax.swing.JTable;
import javax.swing.JScrollPane;
import javax.swing.JButton;
import java.awt.event.MouseListener;
import java.awt.Component;
import java.awt.Container;
import sun.tools.jconsole.MBeansTab;
import sun.tools.jconsole.Messages;
public class XDataViewer {
public static final int OPEN = 1;
public static final int ARRAY = 2;
public static final int NUMERIC = 3;
public static final int NOT_SUPPORTED = 4;
private MBeansTab tab;
public XDataViewer(MBeansTab tab) {
this.tab = tab;
}
public static void registerForMouseEvent(Component comp,
MouseListener mouseListener) {
if(comp instanceof JScrollPane) {
JScrollPane pane = (JScrollPane) comp;
comp = pane.getViewport().getView();
}
if(comp instanceof Container) {
Container container = (Container) comp;
Component[] components = container.getComponents();
for(int i = 0; i < components.length; i++) {
registerForMouseEvent(components[i], mouseListener);
}
}
//No registration for XOpenTypedata that are themselves clickable.
//No registration for JButton that are themselves clickable.
if(comp != null &&
(!(comp instanceof XOpenTypeViewer.XOpenTypeData) &&
!(comp instanceof JButton)) )
comp.addMouseListener(mouseListener);
}
public static void dispose(MBeansTab tab) {
XPlottingViewer.dispose(tab);
}
public static boolean isViewableValue(Object value) {
boolean ret = false;
if((ret = XArrayDataViewer.isViewableValue(value)))
return ret;
if((ret = XOpenTypeViewer.isViewableValue(value)))
return ret;
if((ret = XPlottingViewer.isViewableValue(value)))
return ret;
return ret;
}
public static int getViewerType(Object data) {
if(XArrayDataViewer.isViewableValue(data))
return ARRAY;
if(XOpenTypeViewer.isViewableValue(data))
return OPEN;
if(XPlottingViewer.isViewableValue(data))
return NUMERIC;
return NOT_SUPPORTED;
}
public static String getActionLabel(int type) {
if(type == ARRAY ||
type == OPEN)
return Messages.VISUALIZE;
if(type == NUMERIC)
return Messages.PLOT;
return Messages.EXPAND;
}
public Component createOperationViewer(Object value,
XMBean mbean) {
if(value instanceof Number) return null;
if(value instanceof Component) return (Component) value;
return createAttributeViewer(value, mbean, null, null);
}
public static Component createNotificationViewer(Object value) {
Component comp = null;
if(value instanceof Number) return null;
if((comp = XArrayDataViewer.loadArray(value)) != null)
return comp;
if((comp = XOpenTypeViewer.loadOpenType(value)) != null)
return comp;
return comp;
}
public Component createAttributeViewer(Object value,
XMBean mbean,
String attributeName,
JTable table) {
Component comp = null;
if((comp = XArrayDataViewer.loadArray(value)) != null)
return comp;
if((comp = XOpenTypeViewer.loadOpenType(value)) != null)
return comp;
if((comp = XPlottingViewer.loadPlotting(mbean,
attributeName,
value,
table,
tab)) != null)
return comp;
return comp;
}
}

View File

@@ -0,0 +1,186 @@
/*
* Copyright (c) 2004, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.jconsole.inspector;
import java.io.IOException;
import javax.management.*;
import javax.swing.Icon;
import sun.tools.jconsole.JConsole;
import sun.tools.jconsole.MBeansTab;
import sun.tools.jconsole.ProxyClient.SnapshotMBeanServerConnection;
public class XMBean {
private final MBeansTab mbeansTab;
private final ObjectName objectName;
private Icon icon;
private String text;
private Boolean broadcaster;
private final Object broadcasterLock = new Object();
private MBeanInfo mbeanInfo;
private final Object mbeanInfoLock = new Object();
public XMBean(ObjectName objectName, MBeansTab mbeansTab) {
this.mbeansTab = mbeansTab;
this.objectName = objectName;
text = objectName.getKeyProperty("name");
if (text == null) {
text = objectName.getDomain();
}
if (MBeanServerDelegate.DELEGATE_NAME.equals(objectName)) {
icon = IconManager.MBEANSERVERDELEGATE;
} else {
icon = IconManager.MBEAN;
}
}
MBeanServerConnection getMBeanServerConnection() {
return mbeansTab.getMBeanServerConnection();
}
SnapshotMBeanServerConnection getSnapshotMBeanServerConnection() {
return mbeansTab.getSnapshotMBeanServerConnection();
}
public Boolean isBroadcaster() {
synchronized (broadcasterLock) {
if (broadcaster == null) {
try {
broadcaster = getMBeanServerConnection().isInstanceOf(
getObjectName(),
"javax.management.NotificationBroadcaster");
} catch (Exception e) {
if (JConsole.isDebug()) {
System.err.println("Couldn't check if MBean [" +
objectName + "] is a notification broadcaster");
e.printStackTrace();
}
return false;
}
}
return broadcaster;
}
}
public Object invoke(String operationName) throws Exception {
Object result = getMBeanServerConnection().invoke(
getObjectName(), operationName, new Object[0], new String[0]);
return result;
}
public Object invoke(String operationName, Object params[], String sig[])
throws Exception {
Object result = getMBeanServerConnection().invoke(
getObjectName(), operationName, params, sig);
return result;
}
public void setAttribute(Attribute attribute)
throws AttributeNotFoundException, InstanceNotFoundException,
InvalidAttributeValueException, MBeanException,
ReflectionException, IOException {
getMBeanServerConnection().setAttribute(getObjectName(), attribute);
}
public Object getAttribute(String attributeName)
throws AttributeNotFoundException, InstanceNotFoundException,
MBeanException, ReflectionException, IOException {
return getSnapshotMBeanServerConnection().getAttribute(
getObjectName(), attributeName);
}
public AttributeList getAttributes(String attributeNames[])
throws AttributeNotFoundException, InstanceNotFoundException,
MBeanException, ReflectionException, IOException {
return getSnapshotMBeanServerConnection().getAttributes(
getObjectName(), attributeNames);
}
public AttributeList getAttributes(MBeanAttributeInfo attributeNames[])
throws AttributeNotFoundException, InstanceNotFoundException,
MBeanException, ReflectionException, IOException {
String attributeString[] = new String[attributeNames.length];
for (int i = 0; i < attributeNames.length; i++) {
attributeString[i] = attributeNames[i].getName();
}
return getAttributes(attributeString);
}
public ObjectName getObjectName() {
return objectName;
}
public MBeanInfo getMBeanInfo() throws InstanceNotFoundException,
IntrospectionException, ReflectionException, IOException {
synchronized (mbeanInfoLock) {
if (mbeanInfo == null) {
mbeanInfo = getMBeanServerConnection().getMBeanInfo(objectName);
}
return mbeanInfo;
}
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (obj == this) {
return true;
}
if (!(obj instanceof XMBean)) {
return false;
}
XMBean that = (XMBean) obj;
return getObjectName().equals(that.getObjectName());
}
@Override
public int hashCode() {
return (objectName == null ? 0 : objectName.hashCode());
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public Icon getIcon() {
return icon;
}
public void setIcon(Icon icon) {
this.icon = icon;
}
@Override
public String toString() {
return getText();
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,413 @@
/*
* Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.jconsole.inspector;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.GridLayout;
import java.util.*;
import javax.management.*;
import javax.swing.*;
import javax.swing.border.TitledBorder;
import javax.swing.event.*;
import javax.swing.table.*;
import sun.tools.jconsole.Messages;
import static sun.tools.jconsole.Utilities.*;
@SuppressWarnings("serial")
public class XMBeanInfo extends JPanel {
private static final Color lightYellow = new Color(255, 255, 128);
private final int NAME_COLUMN = 0;
private final int VALUE_COLUMN = 1;
private final String[] columnNames = {
Messages.NAME,
Messages.VALUE
};
private JTable infoTable = new JTable();
private JTable descTable = new JTable();
private JPanel infoBorderPanel = new JPanel(new BorderLayout());
private JPanel descBorderPanel = new JPanel(new BorderLayout());
private static class ReadOnlyDefaultTableModel extends DefaultTableModel {
@Override
public void setValueAt(Object value, int row, int col) {
}
}
private static class TableRowDivider {
private String tableRowDividerText;
public TableRowDivider(String tableRowDividerText) {
this.tableRowDividerText = tableRowDividerText;
}
@Override
public String toString() {
return tableRowDividerText;
}
}
private static MBeanInfoTableCellRenderer renderer =
new MBeanInfoTableCellRenderer();
private static class MBeanInfoTableCellRenderer
extends DefaultTableCellRenderer {
@Override
public Component getTableCellRendererComponent(
JTable table, Object value, boolean isSelected,
boolean hasFocus, int row, int column) {
Component comp = super.getTableCellRendererComponent(
table, value, isSelected, hasFocus, row, column);
if (value instanceof TableRowDivider) {
JLabel label = new JLabel(value.toString());
label.setBackground(ensureContrast(lightYellow,
label.getForeground()));
label.setOpaque(true);
return label;
}
return comp;
}
}
private static TableCellEditor editor =
new MBeanInfoTableCellEditor(new JTextField());
private static class MBeanInfoTableCellEditor
extends Utils.ReadOnlyTableCellEditor {
public MBeanInfoTableCellEditor(JTextField tf) {
super(tf);
}
@Override
public Component getTableCellEditorComponent(
JTable table, Object value, boolean isSelected,
int row, int column) {
Component comp = super.getTableCellEditorComponent(
table, value, isSelected, row, column);
if (value instanceof TableRowDivider) {
JLabel label = new JLabel(value.toString());
label.setBackground(ensureContrast(lightYellow,
label.getForeground()));
label.setOpaque(true);
return label;
}
return comp;
}
}
public XMBeanInfo() {
// Use the grid layout to display the two tables
//
super(new GridLayout(2, 1));
// MBean*Info table
//
infoTable.setModel(new ReadOnlyDefaultTableModel());
infoTable.setRowSelectionAllowed(false);
infoTable.setColumnSelectionAllowed(false);
infoTable.getTableHeader().setReorderingAllowed(false);
((DefaultTableModel) infoTable.getModel()).setColumnIdentifiers(columnNames);
infoTable.getColumnModel().getColumn(NAME_COLUMN).setPreferredWidth(140);
infoTable.getColumnModel().getColumn(NAME_COLUMN).setMaxWidth(140);
infoTable.getColumnModel().getColumn(NAME_COLUMN).setCellRenderer(renderer);
infoTable.getColumnModel().getColumn(VALUE_COLUMN).setCellRenderer(renderer);
infoTable.getColumnModel().getColumn(NAME_COLUMN).setCellEditor(editor);
infoTable.getColumnModel().getColumn(VALUE_COLUMN).setCellEditor(editor);
infoTable.addKeyListener(new Utils.CopyKeyAdapter());
infoTable.setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS);
JScrollPane infoTableScrollPane = new JScrollPane(infoTable);
infoBorderPanel.setBorder(
BorderFactory.createTitledBorder("MBeanInfoPlaceHolder"));
infoBorderPanel.add(infoTableScrollPane);
// Descriptor table
//
descTable.setModel(new ReadOnlyDefaultTableModel());
descTable.setRowSelectionAllowed(false);
descTable.setColumnSelectionAllowed(false);
descTable.getTableHeader().setReorderingAllowed(false);
((DefaultTableModel) descTable.getModel()).setColumnIdentifiers(columnNames);
descTable.getColumnModel().getColumn(NAME_COLUMN).setPreferredWidth(140);
descTable.getColumnModel().getColumn(NAME_COLUMN).setMaxWidth(140);
descTable.getColumnModel().getColumn(NAME_COLUMN).setCellRenderer(renderer);
descTable.getColumnModel().getColumn(VALUE_COLUMN).setCellRenderer(renderer);
descTable.getColumnModel().getColumn(NAME_COLUMN).setCellEditor(editor);
descTable.getColumnModel().getColumn(VALUE_COLUMN).setCellEditor(editor);
descTable.addKeyListener(new Utils.CopyKeyAdapter());
descTable.setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS);
JScrollPane descTableScrollPane = new JScrollPane(descTable);
descBorderPanel.setBorder(
BorderFactory.createTitledBorder(Messages.DESCRIPTOR));
descBorderPanel.add(descTableScrollPane);
// Add the two tables to the grid
//
add(infoBorderPanel);
add(descBorderPanel);
}
// Call on EDT
public void emptyInfoTable() {
DefaultTableModel tableModel = (DefaultTableModel) infoTable.getModel();
while (tableModel.getRowCount() > 0) {
tableModel.removeRow(0);
}
}
// Call on EDT
public void emptyDescTable() {
DefaultTableModel tableModel = (DefaultTableModel) descTable.getModel();
while (tableModel.getRowCount() > 0) {
tableModel.removeRow(0);
}
}
// Call on EDT
private void addDescriptor(Descriptor desc, String text) {
if (desc != null && desc.getFieldNames().length > 0) {
DefaultTableModel tableModel = (DefaultTableModel) descTable.getModel();
Object rowData[] = new Object[2];
rowData[0] = new TableRowDivider(text);
rowData[1] = new TableRowDivider("");
tableModel.addRow(rowData);
for (String fieldName : desc.getFieldNames()) {
rowData[0] = fieldName;
Object fieldValue = desc.getFieldValue(fieldName);
if (fieldValue instanceof boolean[]) {
rowData[1] = Arrays.toString((boolean[]) fieldValue);
} else if (fieldValue instanceof byte[]) {
rowData[1] = Arrays.toString((byte[]) fieldValue);
} else if (fieldValue instanceof char[]) {
rowData[1] = Arrays.toString((char[]) fieldValue);
} else if (fieldValue instanceof double[]) {
rowData[1] = Arrays.toString((double[]) fieldValue);
} else if (fieldValue instanceof float[]) {
rowData[1] = Arrays.toString((float[]) fieldValue);
} else if (fieldValue instanceof int[]) {
rowData[1] = Arrays.toString((int[]) fieldValue);
} else if (fieldValue instanceof long[]) {
rowData[1] = Arrays.toString((long[]) fieldValue);
} else if (fieldValue instanceof short[]) {
rowData[1] = Arrays.toString((short[]) fieldValue);
} else if (fieldValue instanceof Object[]) {
rowData[1] = Arrays.toString((Object[]) fieldValue);
} else {
rowData[1] = fieldValue;
}
tableModel.addRow(rowData);
}
tableModel.newDataAvailable(new TableModelEvent(tableModel));
}
}
// Call on EDT
public void addMBeanInfo(XMBean mbean, MBeanInfo mbeanInfo) {
emptyInfoTable();
emptyDescTable();
((TitledBorder) infoBorderPanel.getBorder()).setTitle(
Messages.MBEAN_INFO);
String text = Messages.INFO + ":";
DefaultTableModel tableModel = (DefaultTableModel) infoTable.getModel();
Object rowData[] = new Object[2];
rowData[0] = new TableRowDivider(text);
rowData[1] = new TableRowDivider("");
tableModel.addRow(rowData);
rowData[0] = Messages.OBJECT_NAME;
rowData[1] = mbean.getObjectName();
tableModel.addRow(rowData);
rowData[0] = Messages.CLASS_NAME;
rowData[1] = mbeanInfo.getClassName();
tableModel.addRow(rowData);
rowData[0] = Messages.DESCRIPTION;
rowData[1] = mbeanInfo.getDescription();
tableModel.addRow(rowData);
addDescriptor(mbeanInfo.getDescriptor(), text);
// MBeanConstructorInfo
//
int i = 0;
for (MBeanConstructorInfo mbci : mbeanInfo.getConstructors()) {
addMBeanConstructorInfo(mbci,
Messages.CONSTRUCTOR + "-" + i + ":");
// MBeanParameterInfo
//
int j = 0;
for (MBeanParameterInfo mbpi : mbci.getSignature()) {
addMBeanParameterInfo(mbpi,
Messages.PARAMETER + "-" + i + "-" + j + ":");
j++;
}
i++;
}
tableModel.newDataAvailable(new TableModelEvent(tableModel));
}
// Call on EDT
public void addMBeanAttributeInfo(MBeanAttributeInfo mbai) {
emptyInfoTable();
emptyDescTable();
((TitledBorder) infoBorderPanel.getBorder()).setTitle(
Messages.MBEAN_ATTRIBUTE_INFO);
String text = Messages.ATTRIBUTE + ":";
DefaultTableModel tableModel = (DefaultTableModel) infoTable.getModel();
Object rowData[] = new Object[2];
rowData[0] = new TableRowDivider(text);
rowData[1] = new TableRowDivider("");
tableModel.addRow(rowData);
rowData[0] = Messages.NAME;
rowData[1] = mbai.getName();
tableModel.addRow(rowData);
rowData[0] = Messages.DESCRIPTION;
rowData[1] = mbai.getDescription();
tableModel.addRow(rowData);
rowData[0] = Messages.READABLE;
rowData[1] = mbai.isReadable();
tableModel.addRow(rowData);
rowData[0] = Messages.WRITABLE;
rowData[1] = mbai.isWritable();
tableModel.addRow(rowData);
rowData[0] = Messages.IS;
rowData[1] = mbai.isIs();
tableModel.addRow(rowData);
rowData[0] = Messages.TYPE;
rowData[1] = mbai.getType();
tableModel.addRow(rowData);
addDescriptor(mbai.getDescriptor(), text);
tableModel.newDataAvailable(new TableModelEvent(tableModel));
}
// Call on EDT
public void addMBeanOperationInfo(MBeanOperationInfo mboi) {
emptyInfoTable();
emptyDescTable();
((TitledBorder) infoBorderPanel.getBorder()).setTitle(
Messages.MBEAN_OPERATION_INFO);
String text = Messages.OPERATION + ":";
DefaultTableModel tableModel = (DefaultTableModel) infoTable.getModel();
Object rowData[] = new Object[2];
rowData[0] = new TableRowDivider(text);
rowData[1] = new TableRowDivider("");
tableModel.addRow(rowData);
rowData[0] = Messages.NAME;
rowData[1] = mboi.getName();
tableModel.addRow(rowData);
rowData[0] = Messages.DESCRIPTION;
rowData[1] = mboi.getDescription();
tableModel.addRow(rowData);
rowData[0] = Messages.IMPACT;
switch (mboi.getImpact()) {
case MBeanOperationInfo.INFO:
rowData[1] = Messages.INFO_CAPITALIZED;
break;
case MBeanOperationInfo.ACTION:
rowData[1] = Messages.ACTION_CAPITALIZED;
break;
case MBeanOperationInfo.ACTION_INFO:
rowData[1] = Messages.ACTION_INFO_CAPITALIZED;
break;
case MBeanOperationInfo.UNKNOWN:
rowData[1] = Messages.UNKNOWN_CAPITALIZED;
break;
}
tableModel.addRow(rowData);
rowData[0] = Messages.RETURN_TYPE;
rowData[1] = mboi.getReturnType();
tableModel.addRow(rowData);
addDescriptor(mboi.getDescriptor(), text);
// MBeanParameterInfo
//
int i = 0;
for (MBeanParameterInfo mbpi : mboi.getSignature()) {
addMBeanParameterInfo(mbpi,
Messages.PARAMETER + "-" + i++ + ":");
}
tableModel.newDataAvailable(new TableModelEvent(tableModel));
}
// Call on EDT
public void addMBeanNotificationInfo(MBeanNotificationInfo mbni) {
emptyInfoTable();
emptyDescTable();
((TitledBorder) infoBorderPanel.getBorder()).setTitle(
Messages.MBEAN_NOTIFICATION_INFO);
String text = Messages.NOTIFICATION + ":";
DefaultTableModel tableModel = (DefaultTableModel) infoTable.getModel();
Object rowData[] = new Object[2];
rowData[0] = new TableRowDivider(text);
rowData[1] = new TableRowDivider("");
tableModel.addRow(rowData);
rowData[0] = Messages.NAME;
rowData[1] = mbni.getName();
tableModel.addRow(rowData);
rowData[0] = Messages.DESCRIPTION;
rowData[1] = mbni.getDescription();
tableModel.addRow(rowData);
rowData[0] = Messages.NOTIF_TYPES;
rowData[1] = Arrays.toString(mbni.getNotifTypes());
tableModel.addRow(rowData);
addDescriptor(mbni.getDescriptor(), text);
tableModel.newDataAvailable(new TableModelEvent(tableModel));
}
// Call on EDT
private void addMBeanConstructorInfo(MBeanConstructorInfo mbci, String text) {
DefaultTableModel tableModel = (DefaultTableModel) infoTable.getModel();
Object rowData[] = new Object[2];
rowData[0] = new TableRowDivider(text);
rowData[1] = new TableRowDivider("");
tableModel.addRow(rowData);
rowData[0] = Messages.NAME;
rowData[1] = mbci.getName();
tableModel.addRow(rowData);
rowData[0] = Messages.DESCRIPTION;
rowData[1] = mbci.getDescription();
tableModel.addRow(rowData);
addDescriptor(mbci.getDescriptor(), text);
tableModel.newDataAvailable(new TableModelEvent(tableModel));
}
// Call on EDT
private void addMBeanParameterInfo(MBeanParameterInfo mbpi, String text) {
DefaultTableModel tableModel = (DefaultTableModel) infoTable.getModel();
Object rowData[] = new Object[2];
rowData[0] = new TableRowDivider(text);
rowData[1] = new TableRowDivider("");
tableModel.addRow(rowData);
rowData[0] = Messages.NAME;
rowData[1] = mbpi.getName();
tableModel.addRow(rowData);
rowData[0] = Messages.DESCRIPTION;
rowData[1] = mbpi.getDescription();
tableModel.addRow(rowData);
rowData[0] = Messages.TYPE;
rowData[1] = mbpi.getType();
tableModel.addRow(rowData);
addDescriptor(mbpi.getDescriptor(), text);
tableModel.newDataAvailable(new TableModelEvent(tableModel));
}
}

View File

@@ -0,0 +1,711 @@
/*
* Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.jconsole.inspector;
import javax.swing.*;
import javax.swing.table.*;
import javax.swing.tree.*;
import java.awt.Font;
import java.text.SimpleDateFormat;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.event.*;
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.JConsole;
import sun.tools.jconsole.Messages;
@SuppressWarnings("serial")
public class XMBeanNotifications extends JTable implements NotificationListener {
private final static String[] columnNames = {
Messages.TIME_STAMP,
Messages.TYPE,
Messages.USER_DATA,
Messages.SEQ_NUM,
Messages.MESSAGE,
Messages.EVENT,
Messages.SOURCE
};
private HashMap<ObjectName, XMBeanNotificationsListener> listeners =
new HashMap<ObjectName, XMBeanNotificationsListener>();
private volatile boolean subscribed;
private XMBeanNotificationsListener currentListener;
public final static String NOTIFICATION_RECEIVED_EVENT =
"jconsole.xnotification.received";
private List<NotificationListener> notificationListenersList;
private volatile boolean enabled;
private Font normalFont, boldFont;
private int rowMinHeight = -1;
private TableCellEditor userDataEditor = new UserDataCellEditor();
private NotifMouseListener mouseListener = new NotifMouseListener();
private SimpleDateFormat timeFormater = new SimpleDateFormat("HH:mm:ss:SSS");
private static TableCellEditor editor =
new Utils.ReadOnlyTableCellEditor(new JTextField());
public XMBeanNotifications() {
super(new TableSorter(columnNames, 0));
setColumnSelectionAllowed(false);
setRowSelectionAllowed(false);
getTableHeader().setReorderingAllowed(false);
ArrayList<NotificationListener> l =
new ArrayList<NotificationListener>(1);
notificationListenersList = Collections.synchronizedList(l);
addMouseListener(mouseListener);
TableColumnModel colModel = getColumnModel();
colModel.getColumn(0).setPreferredWidth(45);
colModel.getColumn(1).setPreferredWidth(50);
colModel.getColumn(2).setPreferredWidth(50);
colModel.getColumn(3).setPreferredWidth(40);
colModel.getColumn(4).setPreferredWidth(50);
colModel.getColumn(5).setPreferredWidth(50);
setColumnEditors();
addKeyListener(new Utils.CopyKeyAdapter());
}
// Call on EDT
public void cancelCellEditing() {
TableCellEditor tce = getCellEditor();
if (tce != null) {
tce.cancelCellEditing();
}
}
// Call on EDT
public void stopCellEditing() {
TableCellEditor tce = getCellEditor();
if (tce != null) {
tce.stopCellEditing();
}
}
// Call on EDT
@Override
public boolean isCellEditable(int row, int col) {
UserDataCell cell = getUserDataCell(row, col);
if (cell != null) {
return cell.isMaximized();
}
return true;
}
// Call on EDT
@Override
public void setValueAt(Object value, int row, int column) {
}
// Call on EDT
@Override
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;
}
Component comp = super.prepareRenderer(renderer, row, column);
if (normalFont == null) {
normalFont = comp.getFont();
boldFont = normalFont.deriveFont(Font.BOLD);
}
UserDataCell cell = getUserDataCell(row, 2);
if (column == 2 && cell != null) {
comp.setFont(boldFont);
int size = cell.getHeight();
if (size > 0) {
if (getRowHeight(row) != size) {
setRowHeight(row, size);
}
}
} else {
comp.setFont(normalFont);
}
return comp;
}
// Call on EDT
@Override
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;
}
DefaultTableCellRenderer renderer;
String toolTip = null;
UserDataCell cell = getUserDataCell(row, column);
if (cell != null && cell.isInited()) {
renderer = (DefaultTableCellRenderer) cell.getRenderer();
} else {
renderer =
(DefaultTableCellRenderer) super.getCellRenderer(row, column);
}
if (cell != null) {
toolTip = Messages.DOUBLE_CLICK_TO_EXPAND_FORWARD_SLASH_COLLAPSE+
". " + cell.toString();
} else {
Object val =
((DefaultTableModel) getModel()).getValueAt(row, column);
if (val != null) {
toolTip = val.toString();
}
}
renderer.setToolTipText(toolTip);
return renderer;
}
// Call on EDT
private UserDataCell getUserDataCell(int row, int column) {
Object obj = ((DefaultTableModel) getModel()).getValueAt(row, column);
if (obj instanceof UserDataCell) {
return (UserDataCell) obj;
}
return null;
}
synchronized void dispose() {
listeners.clear();
}
public long getReceivedNotifications(XMBean mbean) {
XMBeanNotificationsListener listener =
listeners.get(mbean.getObjectName());
if (listener == null) {
return 0;
} else {
return listener.getReceivedNotifications();
}
}
public synchronized boolean clearCurrentNotifications() {
emptyTable();
if (currentListener != null) {
currentListener.clear();
return true;
} else {
return false;
}
}
public synchronized boolean unregisterListener(DefaultMutableTreeNode node) {
XMBean mbean = (XMBean) ((XNodeInfo) node.getUserObject()).getData();
return unregister(mbean.getObjectName());
}
public synchronized void registerListener(DefaultMutableTreeNode node)
throws InstanceNotFoundException, IOException {
XMBean mbean = (XMBean) ((XNodeInfo) node.getUserObject()).getData();
if (!subscribed) {
try {
mbean.getMBeanServerConnection().addNotificationListener(
MBeanServerDelegate.DELEGATE_NAME, this, null, null);
subscribed = true;
} catch (Exception e) {
if (JConsole.isDebug()) {
System.err.println("Error adding listener for delegate:");
e.printStackTrace();
}
}
}
XMBeanNotificationsListener listener =
listeners.get(mbean.getObjectName());
if (listener == null) {
listener = new XMBeanNotificationsListener(
this, mbean, node, columnNames);
listeners.put(mbean.getObjectName(), listener);
} else {
if (!listener.isRegistered()) {
emptyTable();
listener.register(node);
}
}
enabled = true;
currentListener = listener;
}
public synchronized void handleNotification(
Notification notif, Object handback) {
try {
if (notif instanceof MBeanServerNotification) {
ObjectName mbean =
((MBeanServerNotification) notif).getMBeanName();
if (notif.getType().indexOf("JMX.mbean.unregistered") >= 0) {
unregister(mbean);
}
}
} catch (Exception e) {
if (JConsole.isDebug()) {
System.err.println("Error unregistering notification:");
e.printStackTrace();
}
}
}
public synchronized void disableNotifications() {
emptyTable();
currentListener = null;
enabled = false;
}
private synchronized boolean unregister(ObjectName mbean) {
XMBeanNotificationsListener listener = listeners.get(mbean);
if (listener != null && listener.isRegistered()) {
listener.unregister();
return true;
} else {
return false;
}
}
public void addNotificationsListener(NotificationListener nl) {
notificationListenersList.add(nl);
}
public void removeNotificationsListener(NotificationListener nl) {
notificationListenersList.remove(nl);
}
// Call on EDT
void fireNotificationReceived(
XMBeanNotificationsListener listener, XMBean mbean,
DefaultMutableTreeNode node, Object[] rowData, long received) {
if (enabled) {
DefaultTableModel tableModel = (DefaultTableModel) getModel();
if (listener == currentListener) {
tableModel.insertRow(0, rowData);
repaint();
}
}
Notification notif =
new Notification(NOTIFICATION_RECEIVED_EVENT, this, 0);
notif.setUserData(received);
for (NotificationListener nl : notificationListenersList) {
nl.handleNotification(notif, node);
}
}
// Call on EDT
private void updateModel(List<Object[]> data) {
emptyTable();
DefaultTableModel tableModel = (DefaultTableModel) getModel();
for (Object[] rowData : data) {
tableModel.addRow(rowData);
}
}
public synchronized boolean isListenerRegistered(XMBean mbean) {
XMBeanNotificationsListener listener =
listeners.get(mbean.getObjectName());
if (listener == null) {
return false;
}
return listener.isRegistered();
}
// Call on EDT
public synchronized void loadNotifications(XMBean mbean) {
XMBeanNotificationsListener listener =
listeners.get(mbean.getObjectName());
emptyTable();
if (listener != null) {
enabled = true;
List<Object[]> data = listener.getData();
updateModel(data);
currentListener = listener;
validate();
repaint();
} else {
enabled = false;
}
}
// Call on EDT
private void setColumnEditors() {
TableColumnModel tcm = getColumnModel();
for (int i = 0; i < columnNames.length; i++) {
TableColumn tc = tcm.getColumn(i);
if (i == 2) {
tc.setCellEditor(userDataEditor);
} else {
tc.setCellEditor(editor);
}
}
}
// Call on EDT
public boolean isTableEditable() {
return true;
}
// Call on EDT
public synchronized void emptyTable() {
DefaultTableModel model = (DefaultTableModel) getModel();
//invalidate();
while (model.getRowCount() > 0) {
model.removeRow(0);
}
validate();
}
// Call on EDT
synchronized void updateUserDataCell(int row, int col) {
Object obj = getModel().getValueAt(row, 2);
if (obj instanceof UserDataCell) {
UserDataCell cell = (UserDataCell) obj;
if (!cell.isInited()) {
if (rowMinHeight == -1) {
rowMinHeight = getRowHeight(row);
}
cell.init(super.getCellRenderer(row, col), rowMinHeight);
}
cell.switchState();
setRowHeight(row, cell.getHeight());
if (!cell.isMaximized()) {
cancelCellEditing();
//Back to simple editor.
editCellAt(row, 2);
}
invalidate();
repaint();
}
}
class UserDataCellRenderer extends DefaultTableCellRenderer {
Component comp;
UserDataCellRenderer(Component comp) {
this.comp = comp;
Dimension d = comp.getPreferredSize();
if (d.getHeight() > 200) {
comp.setPreferredSize(new Dimension((int) d.getWidth(), 200));
}
}
@Override
public Component getTableCellRendererComponent(
JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row,
int column) {
return comp;
}
public Component getComponent() {
return comp;
}
}
class UserDataCell {
TableCellRenderer minRenderer;
UserDataCellRenderer maxRenderer;
int minHeight;
boolean minimized = true;
boolean init = false;
Object userData;
UserDataCell(Object userData, Component max) {
this.userData = userData;
this.maxRenderer = new UserDataCellRenderer(max);
}
@Override
public String toString() {
if (userData == null) {
return null;
}
if (userData.getClass().isArray()) {
String name =
Utils.getArrayClassName(userData.getClass().getName());
int length = Array.getLength(userData);
return name + "[" + length + "]";
}
if (userData instanceof CompositeData ||
userData instanceof TabularData) {
return userData.getClass().getName();
}
return userData.toString();
}
boolean isInited() {
return init;
}
void init(TableCellRenderer minRenderer, int minHeight) {
this.minRenderer = minRenderer;
this.minHeight = minHeight;
init = 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();
}
}
TableCellRenderer getRenderer() {
if (minimized) {
return minRenderer;
} else {
return maxRenderer;
}
}
}
class NotifMouseListener extends MouseAdapter {
@Override
public void mousePressed(MouseEvent e) {
if (e.getButton() == MouseEvent.BUTTON1) {
if (e.getClickCount() >= 2) {
int row = XMBeanNotifications.this.getSelectedRow();
int col = XMBeanNotifications.this.getSelectedColumn();
if (col != 2) {
return;
}
if (col == -1 || row == -1) {
return;
}
XMBeanNotifications.this.updateUserDataCell(row, col);
}
}
}
}
class UserDataCellEditor extends XTextFieldEditor {
// implements javax.swing.table.TableCellEditor
@Override
public Component getTableCellEditorComponent(
JTable table,
Object value,
boolean isSelected,
int row,
int column) {
Object val = value;
if (column == 2) {
Object obj = getModel().getValueAt(row, column);
if (obj instanceof UserDataCell) {
UserDataCell cell = (UserDataCell) obj;
if (cell.getRenderer() instanceof UserDataCellRenderer) {
UserDataCellRenderer zr =
(UserDataCellRenderer) cell.getRenderer();
return zr.getComponent();
}
} else {
Component comp = super.getTableCellEditorComponent(
table, val, isSelected, row, column);
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 == 2) {
Object obj = getModel().getValueAt(editingRow, editingColumn);
if (obj instanceof UserDataCell) {
UserDataCell cell = (UserDataCell) obj;
if (cell.isMaximized()) {
cancelCellEditing();
return true;
}
}
}
return super.stopCellEditing();
}
}
class XMBeanNotificationsListener implements NotificationListener {
private XMBean xmbean;
private DefaultMutableTreeNode node;
private volatile long received;
private XMBeanNotifications notifications;
private volatile boolean unregistered;
private ArrayList<Object[]> data = new ArrayList<Object[]>();
public XMBeanNotificationsListener(
XMBeanNotifications notifications,
XMBean xmbean,
DefaultMutableTreeNode node,
String[] columnNames) {
this.notifications = notifications;
this.xmbean = xmbean;
this.node = node;
register(node);
}
public synchronized List<Object[]> getData() {
return data;
}
public synchronized void clear() {
data.clear();
received = 0;
}
public synchronized boolean isRegistered() {
return !unregistered;
}
public synchronized void unregister() {
try {
xmbean.getMBeanServerConnection().removeNotificationListener(
xmbean.getObjectName(), this, null, null);
} catch (Exception e) {
if (JConsole.isDebug()) {
System.err.println("Error removing listener:");
e.printStackTrace();
}
}
unregistered = true;
}
public synchronized long getReceivedNotifications() {
return received;
}
public synchronized void register(DefaultMutableTreeNode node) {
clear();
this.node = node;
try {
xmbean.getMBeanServerConnection().addNotificationListener(
xmbean.getObjectName(), this, null, null);
unregistered = false;
} catch (Exception e) {
if (JConsole.isDebug()) {
System.err.println("Error adding listener:");
e.printStackTrace();
}
}
}
public synchronized void handleNotification(
final Notification n, Object hb) {
EventQueue.invokeLater(new Runnable() {
public void run() {
synchronized (XMBeanNotificationsListener.this) {
try {
if (unregistered) {
return;
}
Date receivedDate = new Date(n.getTimeStamp());
String time = timeFormater.format(receivedDate);
Object userData = n.getUserData();
Component comp = null;
UserDataCell cell = null;
if ((comp = XDataViewer.createNotificationViewer(userData)) != null) {
XDataViewer.registerForMouseEvent(comp, mouseListener);
cell = new UserDataCell(userData, comp);
}
Object[] rowData = {
time,
n.getType(),
(cell == null ? userData : cell),
n.getSequenceNumber(),
n.getMessage(),
n,
n.getSource()
};
received++;
data.add(0, rowData);
notifications.fireNotificationReceived(
XMBeanNotificationsListener.this,
xmbean, node, rowData, received);
} catch (Exception e) {
if (JConsole.isDebug()) {
System.err.println("Error handling notification:");
e.printStackTrace();
}
}
}
}
});
}
}
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright (c) 2004, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.jconsole.inspector;
import javax.management.*;
import java.util.ArrayList;
import sun.tools.jconsole.MBeansTab;
@SuppressWarnings("serial")
public class XMBeanOperations extends XOperations {
public XMBeanOperations(MBeansTab mbeansTab) {
super(mbeansTab);
}
protected MBeanOperationInfo[] updateOperations(MBeanOperationInfo[] operations) {
//remove get,set and is
ArrayList<MBeanOperationInfo> mbeanOperations =
new ArrayList<MBeanOperationInfo>(operations.length);
for(MBeanOperationInfo operation : operations) {
if (!( (operation.getSignature().length == 0 &&
operation.getName().startsWith("get") &&
!operation.getReturnType().equals("void")) ||
(operation.getSignature().length == 1 &&
operation.getName().startsWith("set") &&
operation.getReturnType().equals("void")) ||
(operation.getName().startsWith("is") &&
operation.getReturnType().equals("boolean"))
) ) {
mbeanOperations.add(operation);
}
}
return mbeanOperations.toArray(new MBeanOperationInfo[0]);
}
}

View File

@@ -0,0 +1,77 @@
/*
* Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.jconsole.inspector;
/**
* <p>This class represents the user object of the nodes in the MBean tree.</p>
*
* <p>It encapsulates the node's info, i.e. the type of the node, the label to
* be used when displaying the node in the MBean tree, the node's tool tip text
* and arbitrary data which varies depending on the type of the node: an XMBean
* reference for MBEAN, ATTRIBUTES, OPERATIONS and NOTIFICATIONS nodes; the
* corresponding MBeanInfo for ATTRIBUTE, OPERATION and NOTIFICATION nodes;
* it is not used for NONMBEAN nodes.</p>
*/
public class XNodeInfo {
public static enum Type {
MBEAN, NONMBEAN,
ATTRIBUTES, OPERATIONS, NOTIFICATIONS,
ATTRIBUTE, OPERATION, NOTIFICATION
};
public XNodeInfo(Type type, Object data, String label, String tooltip) {
this.type = type;
this.data = data;
this.label = label;
this.tooltip = tooltip;
}
public Type getType() {
return type;
}
public Object getData() {
return data;
}
public String getLabel() {
return label;
}
public String getToolTipText() {
return tooltip;
}
public String toString() {
return label;
}
private Type type;
private Object data;
private String label;
private String tooltip;
}

View File

@@ -0,0 +1,113 @@
/*
* Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.jconsole.inspector;
// java import
import javax.swing.*;
import java.util.Objects;
/**
* This provides a wrapper to the Object class to allow it to be
displayed/manipulated as a GUI object.
*/
@SuppressWarnings("serial")
public class XObject extends JLabel {
private Object object;
private static boolean useHashCodeRepresentation = true;
public final static XObject NULL_OBJECT = new XObject("null");
public XObject (Object object, Icon icon) {
this(object);
setIcon(icon);
}
public XObject (Object object) {
setObject(object);
setHorizontalAlignment(SwingConstants.LEFT);
}
public boolean equals(Object o) {
if (o instanceof XObject) {
return Objects.equals(object, ((XObject)o).getObject());
}
return false;
}
@Override
public int hashCode() {
return object.hashCode();
}
public Object getObject() {
return object;
}
//if true the the object.hashcode is added to the label
public static void
useHashCodeRepresentation(boolean useHashCodeRepresentation) {
XObject.useHashCodeRepresentation = useHashCodeRepresentation;
}
public static boolean hashCodeRepresentation() {
return useHashCodeRepresentation;
}
public void setObject(Object object) {
this.object = object;
// if the object is not a swing component,
// use default icon
try {
String text = null;
if (object instanceof JLabel) {
setIcon(((JLabel)object).getIcon());
if (getText() != null) {
text = ((JLabel)object).getText();
}
}
else if (object instanceof JButton) {
setIcon(((JButton)object).getIcon());
if (getText() != null) {
text = ((JButton)object).getText();
}
}
else if (getText() != null) {
text = object.toString();
setIcon(IconManager.DEFAULT_XOBJECT);
}
if (text != null) {
if (useHashCodeRepresentation && (this != NULL_OBJECT)) {
text = text + " ("+object.hashCode()+")";
}
setText(text);
}
}
catch (Exception e) {
System.out.println("Error setting XObject object :"+
e.getMessage());
}
}
}

View File

@@ -0,0 +1,816 @@
/*
* Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.jconsole.inspector;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Component;
import java.awt.Color;
import java.awt.Font;
import java.awt.event.*;
import java.awt.Dimension;
import java.util.*;
import java.lang.reflect.Array;
import javax.management.openmbean.*;
import sun.tools.jconsole.JConsole;
import sun.tools.jconsole.Messages;
import sun.tools.jconsole.Resources;
@SuppressWarnings("serial")
public class XOpenTypeViewer extends JPanel implements ActionListener {
JButton prev, incr, decr, tabularPrev, tabularNext;
JLabel compositeLabel, tabularLabel;
JScrollPane container;
XOpenTypeData current;
XOpenTypeDataListener listener = new XOpenTypeDataListener();
private static final String compositeNavigationSingle =
Messages.MBEANS_TAB_COMPOSITE_NAVIGATION_SINGLE;
private static final String tabularNavigationSingle =
Messages.MBEANS_TAB_TABULAR_NAVIGATION_SINGLE;
private static TableCellEditor editor =
new Utils.ReadOnlyTableCellEditor(new JTextField());
class XOpenTypeDataListener extends MouseAdapter {
XOpenTypeDataListener() {
}
public void mousePressed(MouseEvent e) {
if(e.getButton() == MouseEvent.BUTTON1) {
if(e.getClickCount() >= 2) {
XOpenTypeData elem = getSelectedViewedOpenType();
if(elem != null) {
try {
elem.viewed(XOpenTypeViewer.this);
}catch(Exception ex) {
//Nothing to change, the element
//can't be displayed
}
}
}
}
}
private XOpenTypeData getSelectedViewedOpenType() {
int row = XOpenTypeViewer.this.current.getSelectedRow();
int col = XOpenTypeViewer.this.current.getSelectedColumn();
Object elem =
XOpenTypeViewer.this.current.getModel().getValueAt(row, col);
if(elem instanceof XOpenTypeData)
return (XOpenTypeData) elem;
else
return null;
}
}
static interface Navigatable {
public void incrElement();
public void decrElement();
public boolean canDecrement();
public boolean canIncrement();
public int getElementCount();
public int getSelectedElementIndex();
}
static interface XViewedTabularData extends Navigatable {
}
static interface XViewedArrayData extends Navigatable {
}
static abstract class XOpenTypeData extends JTable {
XOpenTypeData parent;
protected int col1Width = -1;
protected int col2Width = -1;
private boolean init;
private Font normalFont, boldFont;
protected XOpenTypeData(XOpenTypeData parent) {
this.parent = parent;
}
public XOpenTypeData getViewedParent() {
return parent;
}
public String getToolTip(int row, int col) {
if(col == 1) {
Object value = getModel().getValueAt(row, col);
if (value != null) {
if(isClickableElement(value))
return Messages.DOUBLE_CLICK_TO_VISUALIZE
+ ". " + value.toString();
else
return value.toString();
}
}
return null;
}
public TableCellRenderer getCellRenderer(int row, int column) {
DefaultTableCellRenderer tcr =
(DefaultTableCellRenderer)super.getCellRenderer(row,column);
tcr.setToolTipText(getToolTip(row,column));
return tcr;
}
public void renderKey(String key, Component comp) {
comp.setFont(normalFont);
}
public Component prepareRenderer(TableCellRenderer renderer,
int row, int column) {
Component comp = super.prepareRenderer(renderer, row, column);
if (normalFont == null) {
normalFont = comp.getFont();
boldFont = normalFont.deriveFont(Font.BOLD);
}
Object o = ((DefaultTableModel) getModel()).getValueAt(row, column);
if (column == 0) {
String key = o.toString();
renderKey(key, comp);
} else {
if (isClickableElement(o)) {
comp.setFont(boldFont);
} else {
comp.setFont(normalFont);
}
}
return comp;
}
protected boolean isClickableElement(Object obj) {
if (obj instanceof XOpenTypeData) {
if (obj instanceof Navigatable) {
return (((Navigatable) obj).getElementCount() != 0);
} else {
return (obj instanceof XCompositeData);
}
}
return false;
}
protected void updateColumnWidth() {
if (!init) {
TableColumnModel colModel = getColumnModel();
if (col2Width == -1) {
col1Width = col1Width * 7;
if (col1Width <
getPreferredScrollableViewportSize().getWidth()) {
col1Width = (int)
getPreferredScrollableViewportSize().getWidth();
}
colModel.getColumn(0).setPreferredWidth(col1Width);
init = true;
return;
}
col1Width = (col1Width * 7) + 7;
col1Width = Math.max(col1Width, 70);
col2Width = (col2Width * 7) + 7;
if (col1Width + col2Width <
getPreferredScrollableViewportSize().getWidth()) {
col2Width = (int)
getPreferredScrollableViewportSize().getWidth() -
col1Width;
}
colModel.getColumn(0).setPreferredWidth(col1Width);
colModel.getColumn(1).setPreferredWidth(col2Width);
init = true;
}
}
public abstract void viewed(XOpenTypeViewer viewer) throws Exception;
protected void initTable(String[] columnNames) {
setRowSelectionAllowed(false);
setColumnSelectionAllowed(false);
getTableHeader().setReorderingAllowed(false);
((DefaultTableModel) getModel()).setColumnIdentifiers(columnNames);
for (Enumeration<TableColumn> e = getColumnModel().getColumns();
e.hasMoreElements();) {
TableColumn tc = e.nextElement();
tc.setCellEditor(editor);
}
addKeyListener(new Utils.CopyKeyAdapter());
setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS);
setPreferredScrollableViewportSize(new Dimension(350, 200));
}
protected void emptyTable() {
invalidate();
while (getModel().getRowCount()>0)
((DefaultTableModel) getModel()).removeRow(0);
validate();
}
public void setValueAt(Object value, int row, int col) {
}
}
static class TabularDataComparator implements Comparator<CompositeData> {
private final List<String> indexNames;
public TabularDataComparator(TabularType type) {
indexNames = type.getIndexNames();
}
@SuppressWarnings("unchecked")
public int compare(CompositeData o1, CompositeData o2) {
for (String key : indexNames) {
Object c1 = o1.get(key);
Object c2 = o2.get(key);
if (c1 instanceof Comparable && c2 instanceof Comparable) {
int result = ((Comparable<Object>) c1).compareTo(c2);
if (result != 0)
return result;
}
}
return 0;
}
}
static class XTabularData extends XCompositeData
implements XViewedTabularData {
final TabularData tabular;
final TabularType type;
int currentIndex = 0;
final Object[] elements;
final int size;
private Font normalFont, italicFont;
@SuppressWarnings("unchecked")
public XTabularData(XOpenTypeData parent, TabularData tabular) {
super(parent, accessFirstElement(tabular));
this.tabular = tabular;
type = tabular.getTabularType();
size = tabular.values().size();
if (size > 0) {
// Order tabular data elements using index names
List<CompositeData> data = new ArrayList<CompositeData>(
(Collection<CompositeData>) tabular.values());
Collections.sort(data, new TabularDataComparator(type));
elements = data.toArray();
loadCompositeData((CompositeData) elements[0]);
} else {
elements = new Object[0];
}
}
private static CompositeData accessFirstElement(TabularData tabular) {
if(tabular.values().size() == 0) return null;
return (CompositeData) tabular.values().toArray()[0];
}
public void renderKey(String key, Component comp) {
if (normalFont == null) {
normalFont = comp.getFont();
italicFont = normalFont.deriveFont(Font.ITALIC);
}
for(Object k : type.getIndexNames()) {
if(key.equals(k))
comp.setFont(italicFont);
}
}
public int getElementCount() {
return size;
}
public int getSelectedElementIndex() {
return currentIndex;
}
public void incrElement() {
currentIndex++;
loadCompositeData((CompositeData)elements[currentIndex]);
}
public void decrElement() {
currentIndex--;
loadCompositeData((CompositeData)elements[currentIndex]);
}
public boolean canDecrement() {
if(currentIndex == 0)
return false;
else
return true;
}
public boolean canIncrement(){
if(size == 0 ||
currentIndex == size -1)
return false;
else
return true;
}
public String toString() {
return type == null ? "" : type.getDescription();
}
}
static class XCompositeData extends XOpenTypeData {
protected final String[] columnNames = {
Messages.NAME, Messages.VALUE
};
CompositeData composite;
public XCompositeData() {
super(null);
initTable(columnNames);
}
//In sync with array, no init table.
public XCompositeData(XOpenTypeData parent) {
super(parent);
}
public XCompositeData(XOpenTypeData parent,
CompositeData composite) {
super(parent);
initTable(columnNames);
if(composite != null) {
this.composite = composite;
loadCompositeData(composite);
}
}
public void viewed(XOpenTypeViewer viewer) throws Exception {
viewer.setOpenType(this);
updateColumnWidth();
}
public String toString() {
return composite == null ? "" :
composite.getCompositeType().getTypeName();
}
protected Object formatKey(String key) {
return key;
}
private void load(CompositeData data) {
CompositeType type = data.getCompositeType();
Set<String> keys = type.keySet();
Iterator<String> it = keys.iterator();
Object[] rowData = new Object[2];
while (it.hasNext()) {
String key = (String) it.next();
Object val = data.get(key);
rowData[0] = formatKey(key);
if (val == null) {
rowData[1] = "";
} else {
OpenType<?> openType = type.getType(key);
if (openType instanceof CompositeType) {
rowData[1] =
new XCompositeData(this, (CompositeData) val);
} else if (openType instanceof ArrayType) {
rowData[1] =
new XArrayData(this, (ArrayType<?>) openType, val);
} else if (openType instanceof SimpleType) {
rowData[1] = val;
} else if (openType instanceof TabularType) {
rowData[1] = new XTabularData(this, (TabularData) val);
}
}
// 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();
}
}
((DefaultTableModel) getModel()).addRow(rowData);
}
}
protected void loadCompositeData(CompositeData data) {
composite = data;
emptyTable();
load(data);
DefaultTableModel tableModel = (DefaultTableModel) getModel();
tableModel.newDataAvailable(new TableModelEvent(tableModel));
}
}
static class XArrayData extends XCompositeData
implements XViewedArrayData {
private int dimension;
private int size;
private OpenType<?> elemType;
private Object val;
private boolean isCompositeType;
private boolean isTabularType;
private int currentIndex;
private CompositeData[] elements;
private final String[] arrayColumns = {Messages.VALUE};
private Font normalFont, boldFont;
XArrayData(XOpenTypeData parent, ArrayType<?> type, Object val) {
this(parent, type.getDimension(), type.getElementOpenType(), val);
}
XArrayData(XOpenTypeData parent, int dimension,
OpenType<?> elemType, Object val) {
super(parent);
this.dimension = dimension;
this.elemType = elemType;
this.val = val;
String[] columns = null;
if (dimension > 1) return;
isCompositeType = (elemType instanceof CompositeType);
isTabularType = (elemType instanceof TabularType);
columns = isCompositeType ? columnNames : arrayColumns;
initTable(columns);
loadArray();
}
public void viewed(XOpenTypeViewer viewer) throws Exception {
if (size == 0)
throw new Exception(Messages.EMPTY_ARRAY);
if (dimension > 1)
throw new Exception(Messages.DIMENSION_IS_NOT_SUPPORTED_COLON +
dimension);
super.viewed(viewer);
}
public int getElementCount() {
return size;
}
public int getSelectedElementIndex() {
return currentIndex;
}
public void renderKey(String key, Component comp) {
if (normalFont == null) {
normalFont = comp.getFont();
boldFont = normalFont.deriveFont(Font.BOLD);
}
if (isTabularType) {
comp.setFont(boldFont);
}
}
public void incrElement() {
currentIndex++;
loadCompositeData(elements[currentIndex]);
}
public void decrElement() {
currentIndex--;
loadCompositeData(elements[currentIndex]);
}
public boolean canDecrement() {
if (isCompositeType && currentIndex > 0) {
return true;
}
return false;
}
public boolean canIncrement() {
if (isCompositeType && currentIndex < size - 1) {
return true;
}
return false;
}
private void loadArray() {
if (isCompositeType) {
elements = (CompositeData[]) val;
size = elements.length;
if (size != 0) {
loadCompositeData(elements[0]);
}
} else {
load();
}
}
private void load() {
Object[] rowData = new Object[1];
size = Array.getLength(val);
for (int i = 0; i < size; i++) {
rowData[0] = isTabularType ?
new XTabularData(this, (TabularData) Array.get(val, i)) :
Array.get(val, i);
String str = rowData[0].toString();
if (str.length() > col1Width) {
col1Width = str.length();
}
((DefaultTableModel) getModel()).addRow(rowData);
}
}
public String toString() {
if (dimension > 1) {
return Messages.DIMENSION_IS_NOT_SUPPORTED_COLON +
dimension;
} else {
return elemType.getTypeName() + "[" + size + "]";
}
}
}
/**
* The supplied value is viewable iff:
* - it's a CompositeData/TabularData, or
* - it's a non-empty array of CompositeData/TabularData, or
* - it's a non-empty Collection of CompositeData/TabularData.
*/
public static boolean isViewableValue(Object value) {
// Check for CompositeData/TabularData
//
if (value instanceof CompositeData || value instanceof TabularData) {
return true;
}
// Check for non-empty array of CompositeData/TabularData
//
if (value instanceof CompositeData[] || value instanceof TabularData[]) {
return Array.getLength(value) > 0;
}
// Check for non-empty Collection of CompositeData/TabularData
//
if (value instanceof Collection) {
Collection<?> c = (Collection<?>) value;
if (c.isEmpty()) {
// Empty Collections are not viewable
//
return false;
} else {
// Only Collections of CompositeData/TabularData are viewable
//
return Utils.isUniformCollection(c, CompositeData.class) ||
Utils.isUniformCollection(c, TabularData.class);
}
}
return false;
}
public static Component loadOpenType(Object value) {
Component comp = null;
if(isViewableValue(value)) {
XOpenTypeViewer open =
new XOpenTypeViewer(value);
comp = open;
}
return comp;
}
private XOpenTypeViewer(Object value) {
XOpenTypeData comp = null;
if (value instanceof CompositeData) {
comp = new XCompositeData(null, (CompositeData) value);
} else if (value instanceof TabularData) {
comp = new XTabularData(null, (TabularData) value);
} else if (value instanceof CompositeData[]) {
CompositeData cda[] = (CompositeData[]) value;
CompositeType ct = cda[0].getCompositeType();
comp = new XArrayData(null, 1, ct, cda);
} else if (value instanceof TabularData[]) {
TabularData tda[] = (TabularData[]) value;
TabularType tt = tda[0].getTabularType();
comp = new XArrayData(null, 1, tt, tda);
} else if (value instanceof Collection) {
// At this point we know 'value' is a uniform collection, either
// Collection<CompositeData> or Collection<TabularData>, because
// isViewableValue() has been called before calling the private
// XOpenTypeViewer() constructor.
//
Object e = ((Collection<?>) value).iterator().next();
if (e instanceof CompositeData) {
Collection<?> cdc = (Collection<?>) value;
CompositeData cda[] = cdc.toArray(new CompositeData[0]);
CompositeType ct = cda[0].getCompositeType();
comp = new XArrayData(null, 1, ct, cda);
} else if (e instanceof TabularData) {
Collection<?> tdc = (Collection<?>) value;
TabularData tda[] = tdc.toArray(new TabularData[0]);
TabularType tt = tda[0].getTabularType();
comp = new XArrayData(null, 1, tt, tda);
}
}
setupDisplay(comp);
try {
comp.viewed(this);
} catch (Exception e) {
// Nothing to change, the element can't be displayed
if (JConsole.isDebug()) {
System.out.println("Exception viewing openType : " + e);
e.printStackTrace();
}
}
}
void setOpenType(XOpenTypeData data) {
if (current != null) {
current.removeMouseListener(listener);
}
current = data;
// Enable/Disable the previous (<<) button
if (current.getViewedParent() == null) {
prev.setEnabled(false);
} else {
prev.setEnabled(true);
}
// Set the listener to handle double-click mouse events
current.addMouseListener(listener);
// Enable/Disable the tabular buttons
if (!(data instanceof XViewedTabularData)) {
tabularPrev.setEnabled(false);
tabularNext.setEnabled(false);
tabularLabel.setText(tabularNavigationSingle);
tabularLabel.setEnabled(false);
} else {
XViewedTabularData tabular = (XViewedTabularData) data;
tabularNext.setEnabled(tabular.canIncrement());
tabularPrev.setEnabled(tabular.canDecrement());
boolean hasMoreThanOneElement =
tabular.canIncrement() || tabular.canDecrement();
if (hasMoreThanOneElement) {
tabularLabel.setText(
Resources.format(Messages.MBEANS_TAB_TABULAR_NAVIGATION_MULTIPLE,
String.format("%d", tabular.getSelectedElementIndex() + 1),
String.format("%d", tabular.getElementCount())));
} else {
tabularLabel.setText(tabularNavigationSingle);
}
tabularLabel.setEnabled(hasMoreThanOneElement);
}
// Enable/Disable the composite buttons
if (!(data instanceof XViewedArrayData)) {
incr.setEnabled(false);
decr.setEnabled(false);
compositeLabel.setText(compositeNavigationSingle);
compositeLabel.setEnabled(false);
} else {
XViewedArrayData array = (XViewedArrayData) data;
incr.setEnabled(array.canIncrement());
decr.setEnabled(array.canDecrement());
boolean hasMoreThanOneElement =
array.canIncrement() || array.canDecrement();
if (hasMoreThanOneElement) {
compositeLabel.setText(
Resources.format(Messages.MBEANS_TAB_COMPOSITE_NAVIGATION_MULTIPLE,
String.format("%d", array.getSelectedElementIndex() + 1),
String.format("%d", array.getElementCount())));
} else {
compositeLabel.setText(compositeNavigationSingle);
}
compositeLabel.setEnabled(hasMoreThanOneElement);
}
container.invalidate();
container.setViewportView(current);
container.validate();
}
public void actionPerformed(ActionEvent event) {
if (event.getSource() instanceof JButton) {
JButton b = (JButton) event.getSource();
if (b == prev) {
XOpenTypeData parent = current.getViewedParent();
try {
parent.viewed(this);
} catch (Exception e) {
//Nothing to change, the element can't be displayed
}
} else if (b == incr) {
((XViewedArrayData) current).incrElement();
try {
current.viewed(this);
} catch (Exception e) {
//Nothing to change, the element can't be displayed
}
} else if (b == decr) {
((XViewedArrayData) current).decrElement();
try {
current.viewed(this);
} catch (Exception e) {
//Nothing to change, the element can't be displayed
}
} else if (b == tabularNext) {
((XViewedTabularData) current).incrElement();
try {
current.viewed(this);
} catch (Exception e) {
//Nothing to change, the element can't be displayed
}
} else if (b == tabularPrev) {
((XViewedTabularData) current).decrElement();
try {
current.viewed(this);
} catch (Exception e) {
//Nothing to change, the element can't be displayed
}
}
}
}
private void setupDisplay(XOpenTypeData data) {
setBackground(Color.white);
container =
new JScrollPane(data,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
JPanel buttons = new JPanel(new FlowLayout(FlowLayout.LEFT));
tabularPrev = new JButton(Messages.LESS_THAN);
tabularNext = new JButton(Messages.GREATER_THAN);
JPanel tabularButtons = new JPanel(new FlowLayout(FlowLayout.LEFT));
tabularButtons.add(tabularPrev);
tabularPrev.addActionListener(this);
tabularLabel = new JLabel(tabularNavigationSingle);
tabularLabel.setEnabled(false);
tabularButtons.add(tabularLabel);
tabularButtons.add(tabularNext);
tabularNext.addActionListener(this);
tabularButtons.setBackground(Color.white);
prev = new JButton(Messages.A_LOT_LESS_THAN);
prev.addActionListener(this);
buttons.add(prev);
incr = new JButton(Messages.GREATER_THAN);
incr.addActionListener(this);
decr = new JButton(Messages.LESS_THAN);
decr.addActionListener(this);
JPanel array = new JPanel();
array.setBackground(Color.white);
array.add(decr);
compositeLabel = new JLabel(compositeNavigationSingle);
compositeLabel.setEnabled(false);
array.add(compositeLabel);
array.add(incr);
buttons.add(array);
setLayout(new BorderLayout());
buttons.setBackground(Color.white);
JPanel navigationPanel = new JPanel(new BorderLayout());
navigationPanel.setBackground(Color.white);
navigationPanel.add(tabularButtons, BorderLayout.NORTH);
navigationPanel.add(buttons, BorderLayout.WEST);
add(navigationPanel, BorderLayout.NORTH);
add(container, BorderLayout.CENTER);
Dimension d = new Dimension((int)container.getPreferredSize().
getWidth() + 20,
(int)container.getPreferredSize().
getHeight() + 20);
setPreferredSize(d);
}
}

View File

@@ -0,0 +1,222 @@
/*
* Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.jconsole.inspector;
import javax.swing.*;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.FlowLayout;
import java.awt.Component;
import java.awt.event.*;
import java.util.*;
import javax.management.*;
import sun.tools.jconsole.MBeansTab;
import sun.tools.jconsole.JConsole;
import sun.tools.jconsole.Messages;
public abstract class XOperations extends JPanel implements ActionListener {
public final static String OPERATION_INVOCATION_EVENT =
"jam.xoperations.invoke.result";
private java.util.List<NotificationListener> notificationListenersList;
private Hashtable<JButton, OperationEntry> operationEntryTable;
private XMBean mbean;
private MBeanInfo mbeanInfo;
private MBeansTab mbeansTab;
public XOperations(MBeansTab mbeansTab) {
super(new GridLayout(1, 1));
this.mbeansTab = mbeansTab;
operationEntryTable = new Hashtable<JButton, OperationEntry>();
ArrayList<NotificationListener> l =
new ArrayList<NotificationListener>(1);
notificationListenersList =
Collections.synchronizedList(l);
}
// Call on EDT
public void removeOperations() {
removeAll();
}
// Call on EDT
public void loadOperations(XMBean mbean, MBeanInfo mbeanInfo) {
this.mbean = mbean;
this.mbeanInfo = mbeanInfo;
// add operations information
MBeanOperationInfo operations[] = mbeanInfo.getOperations();
invalidate();
// remove listeners, if any
Component listeners[] = getComponents();
for (int i = 0; i < listeners.length; i++) {
if (listeners[i] instanceof JButton) {
((JButton) listeners[i]).removeActionListener(this);
}
}
removeAll();
setLayout(new BorderLayout());
JButton methodButton;
JLabel methodLabel;
JPanel innerPanelLeft, innerPanelRight;
JPanel outerPanelLeft, outerPanelRight;
outerPanelLeft = new JPanel(new GridLayout(operations.length, 1));
outerPanelRight = new JPanel(new GridLayout(operations.length, 1));
for (int i = 0; i < operations.length; i++) {
innerPanelLeft = new JPanel(new FlowLayout(FlowLayout.RIGHT));
innerPanelRight = new JPanel(new FlowLayout(FlowLayout.LEFT));
String returnType = operations[i].getReturnType();
if (returnType == null) {
methodLabel = new JLabel("null", JLabel.RIGHT);
if (JConsole.isDebug()) {
System.err.println(
"WARNING: The operation's return type " +
"shouldn't be \"null\". Check how the " +
"MBeanOperationInfo for the \"" +
operations[i].getName() + "\" operation has " +
"been defined in the MBean's implementation code.");
}
} else {
methodLabel = new JLabel(
Utils.getReadableClassName(returnType), JLabel.RIGHT);
}
innerPanelLeft.add(methodLabel);
if (methodLabel.getText().length() > 20) {
methodLabel.setText(methodLabel.getText().
substring(methodLabel.getText().
lastIndexOf(".") + 1,
methodLabel.getText().length()));
}
methodButton = new JButton(operations[i].getName());
methodButton.setToolTipText(operations[i].getDescription());
boolean callable = isCallable(operations[i].getSignature());
if (callable) {
methodButton.addActionListener(this);
} else {
methodButton.setEnabled(false);
}
MBeanParameterInfo[] signature = operations[i].getSignature();
OperationEntry paramEntry = new OperationEntry(operations[i],
callable,
methodButton,
this);
operationEntryTable.put(methodButton, paramEntry);
innerPanelRight.add(methodButton);
if (signature.length == 0) {
innerPanelRight.add(new JLabel("( )", JLabel.CENTER));
} else {
innerPanelRight.add(paramEntry);
}
outerPanelLeft.add(innerPanelLeft, BorderLayout.WEST);
outerPanelRight.add(innerPanelRight, BorderLayout.CENTER);
}
add(outerPanelLeft, BorderLayout.WEST);
add(outerPanelRight, BorderLayout.CENTER);
validate();
}
private boolean isCallable(MBeanParameterInfo[] signature) {
for (int i = 0; i < signature.length; i++) {
if (!Utils.isEditableType(signature[i].getType())) {
return false;
}
}
return true;
}
// Call on EDT
public void actionPerformed(final ActionEvent e) {
performInvokeRequest((JButton) e.getSource());
}
void performInvokeRequest(final JButton button) {
final OperationEntry entryIf = operationEntryTable.get(button);
new SwingWorker<Object, Void>() {
@Override
public Object doInBackground() throws Exception {
return mbean.invoke(button.getText(),
entryIf.getParameters(), entryIf.getSignature());
}
@Override
protected void done() {
try {
Object result = get();
// sends result notification to upper level if
// there is a return value
if (entryIf.getReturnType() != null &&
!entryIf.getReturnType().equals(Void.TYPE.getName()) &&
!entryIf.getReturnType().equals(Void.class.getName())) {
fireChangedNotification(OPERATION_INVOCATION_EVENT, button, result);
} else {
new ThreadDialog(
button,
Messages.METHOD_SUCCESSFULLY_INVOKED,
Messages.INFO,
JOptionPane.INFORMATION_MESSAGE).run();
}
} catch (Throwable t) {
t = Utils.getActualException(t);
if (JConsole.isDebug()) {
t.printStackTrace();
}
new ThreadDialog(
button,
Messages.PROBLEM_INVOKING + " " +
button.getText() + " : " + t.toString(),
Messages.ERROR,
JOptionPane.ERROR_MESSAGE).run();
}
}
}.execute();
}
public void addOperationsListener(NotificationListener nl) {
notificationListenersList.add(nl);
}
public void removeOperationsListener(NotificationListener nl) {
notificationListenersList.remove(nl);
}
// Call on EDT
private void fireChangedNotification(
String type, Object source, Object handback) {
Notification n = new Notification(type, source, 0);
for (NotificationListener nl : notificationListenersList) {
nl.handleNotification(n, handback);
}
}
protected abstract MBeanOperationInfo[] updateOperations(MBeanOperationInfo[] operations);
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.jconsole.inspector;
import sun.tools.jconsole.Plotter;
import javax.swing.JTable;
@SuppressWarnings("serial")
public class XPlotter extends Plotter {
JTable table;
public XPlotter(JTable table,
Plotter.Unit unit) {
super(unit,0,false);
this.table = table;
}
@Override
public void addValues(long time, long... values) {
super.addValues(time, values);
table.repaint();
}
}

View File

@@ -0,0 +1,218 @@
/*
* Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.jconsole.inspector;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.util.Timer;
import javax.swing.*;
import sun.tools.jconsole.*;
@SuppressWarnings("serial")
public class XPlottingViewer extends PlotterPanel implements ActionListener {
// TODO: Make number of decimal places customizable
private static final int PLOTTER_DECIMALS = 4;
private JButton plotButton;
// The plotter cache holds Plotter instances for the various attributes
private static HashMap<String, XPlottingViewer> plotterCache =
new HashMap<String, XPlottingViewer>();
private static HashMap<String, Timer> timerCache =
new HashMap<String, Timer>();
private MBeansTab tab;
private String attributeName;
private String key;
private JTable table;
private XPlottingViewer(String key,
XMBean mbean,
String attributeName,
Object value,
JTable table,
MBeansTab tab) {
super(null);
this.tab = tab;
this.key = key;
this.table = table;
this.attributeName = attributeName;
Plotter plotter = createPlotter(mbean, attributeName, key, table);
setupDisplay(plotter);
}
static void dispose(MBeansTab tab) {
Iterator<String> it = plotterCache.keySet().iterator();
while(it.hasNext()) {
String key = it.next();
if(key.startsWith(String.valueOf(tab.hashCode()))) {
it.remove();
}
}
//plotterCache.clear();
it = timerCache.keySet().iterator();
while(it.hasNext()) {
String key = (String) it.next();
if(key.startsWith(String.valueOf(tab.hashCode()))) {
Timer t = timerCache.get(key);
t.cancel();
it.remove();
}
}
}
public static boolean isViewableValue(Object value) {
return (value instanceof Number);
}
//Fired by dbl click
public static Component loadPlotting(XMBean mbean,
String attributeName,
Object value,
JTable table,
MBeansTab tab) {
Component comp = null;
if(isViewableValue(value)) {
String key = String.valueOf(tab.hashCode()) + " " + String.valueOf(mbean.hashCode()) + " " + mbean.getObjectName().getCanonicalName() + attributeName;
XPlottingViewer plotter = plotterCache.get(key);
if(plotter == null) {
plotter = new XPlottingViewer(key,
mbean,
attributeName,
value,
table,
tab);
plotterCache.put(key, plotter);
}
comp = plotter;
}
return comp;
}
/*public void paintComponent(Graphics g) {
super.paintComponent(g);
setBackground(g.getColor());
plotter.paintComponent(g);
}*/
@Override
public void actionPerformed(ActionEvent evt) {
plotterCache.remove(key);
Timer t = timerCache.remove(key);
t.cancel();
((XMBeanAttributes) table).collapse(attributeName, this);
}
//Create plotter instance
public Plotter createPlotter(final XMBean xmbean,
final String attributeName,
String key,
JTable table) {
final Plotter plotter = new XPlotter(table, Plotter.Unit.NONE) {
Dimension prefSize = new Dimension(400, 170);
@Override
public Dimension getPreferredSize() {
return prefSize;
}
@Override
public Dimension getMinimumSize() {
return prefSize;
}
};
plotter.createSequence(attributeName, attributeName, null, true);
TimerTask timerTask = new TimerTask() {
public void run() {
tab.workerAdd(new Runnable() {
public void run() {
try {
Number n =
(Number) xmbean.getSnapshotMBeanServerConnection().getAttribute(xmbean.getObjectName(), attributeName);
long v;
if (n instanceof Float || n instanceof Double) {
plotter.setDecimals(PLOTTER_DECIMALS);
double d = (n instanceof Float) ? (Float)n : (Double)n;
v = Math.round(d * Math.pow(10.0, PLOTTER_DECIMALS));
} else {
v = n.longValue();
}
plotter.addValues(System.currentTimeMillis(), v);
} catch (Exception ex) {
// Should have a trace logged with proper
// trace mecchanism
}
}
});
}
};
String timerName = "Timer-" + key;
Timer timer = new Timer(timerName, true);
timer.schedule(timerTask, 0, tab.getUpdateInterval());
timerCache.put(key, timer);
return plotter;
}
private void setupDisplay(Plotter plotter) {
final JPanel buttonPanel = new JPanel();
final GridBagLayout gbl = new GridBagLayout();
buttonPanel.setLayout(gbl);
setLayout(new BorderLayout());
plotButton = new JButton(Messages.DISCARD_CHART);
plotButton.addActionListener(this);
plotButton.setEnabled(true);
GridBagConstraints buttonConstraints = new GridBagConstraints();
buttonConstraints.gridx = 0;
buttonConstraints.gridy = 0;
buttonConstraints.fill = GridBagConstraints.VERTICAL;
buttonConstraints.anchor = GridBagConstraints.CENTER;
gbl.setConstraints(plotButton, buttonConstraints);
buttonPanel.add(plotButton);
if (attributeName != null && attributeName.length()!=0) {
final JPanel plotterLabelPanel = new JPanel();
final JLabel label = new JLabel(attributeName);
final GridBagLayout gbl2 = new GridBagLayout();
plotterLabelPanel.setLayout(gbl2);
final GridBagConstraints labelConstraints = new GridBagConstraints();
labelConstraints.gridx = 0;
labelConstraints.gridy = 0;
labelConstraints.fill = GridBagConstraints.VERTICAL;
labelConstraints.anchor = GridBagConstraints.CENTER;
labelConstraints.ipady = 10;
gbl2.setConstraints(label, labelConstraints);
plotterLabelPanel.add(label);
add(plotterLabelPanel, BorderLayout.NORTH);
}
setPlotter(plotter);
add(buttonPanel, BorderLayout.SOUTH);
repaint();
}
}

View File

@@ -0,0 +1,749 @@
/*
* Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.jconsole.inspector;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import javax.management.IntrospectionException;
import javax.management.NotificationListener;
import javax.management.MBeanInfo;
import javax.management.InstanceNotFoundException;
import javax.management.ReflectionException;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanNotificationInfo;
import javax.management.Notification;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingWorker;
import javax.swing.border.LineBorder;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import sun.tools.jconsole.*;
import sun.tools.jconsole.inspector.XNodeInfo.Type;
@SuppressWarnings("serial")
public class XSheet extends JPanel
implements ActionListener, NotificationListener {
private JPanel mainPanel;
private JPanel southPanel;
// Node being currently displayed
private volatile DefaultMutableTreeNode currentNode;
// MBean being currently displayed
private volatile XMBean mbean;
// XMBeanAttributes container
private XMBeanAttributes mbeanAttributes;
// XMBeanOperations container
private XMBeanOperations mbeanOperations;
// XMBeanNotifications container
private XMBeanNotifications mbeanNotifications;
// XMBeanInfo container
private XMBeanInfo mbeanInfo;
// Refresh JButton (mbean attributes case)
private JButton refreshButton;
// Subscribe/Unsubscribe/Clear JButton (mbean notifications case)
private JButton clearButton, subscribeButton, unsubscribeButton;
// Reference to MBeans tab
private MBeansTab mbeansTab;
public XSheet(MBeansTab mbeansTab) {
this.mbeansTab = mbeansTab;
setupScreen();
}
public void dispose() {
clear();
XDataViewer.dispose(mbeansTab);
mbeanNotifications.dispose();
}
private void setupScreen() {
setLayout(new BorderLayout());
setBorder(BorderFactory.createLineBorder(Color.GRAY));
// add main panel to XSheet
mainPanel = new JPanel();
mainPanel.setLayout(new BorderLayout());
add(mainPanel, BorderLayout.CENTER);
// add south panel to XSheet
southPanel = new JPanel();
add(southPanel, BorderLayout.SOUTH);
// create the refresh button
refreshButton = new JButton(Messages.MBEANS_TAB_REFRESH_ATTRIBUTES_BUTTON);
refreshButton.setMnemonic(Resources.getMnemonicInt(Messages.MBEANS_TAB_REFRESH_ATTRIBUTES_BUTTON));
refreshButton.setToolTipText(Messages.MBEANS_TAB_REFRESH_ATTRIBUTES_BUTTON_TOOLTIP);
refreshButton.addActionListener(this);
// create the clear button
clearButton = new JButton(Messages.MBEANS_TAB_CLEAR_NOTIFICATIONS_BUTTON);
clearButton.setMnemonic(Resources.getMnemonicInt(Messages.MBEANS_TAB_CLEAR_NOTIFICATIONS_BUTTON));
clearButton.setToolTipText(Messages.MBEANS_TAB_CLEAR_NOTIFICATIONS_BUTTON_TOOLTIP);
clearButton.addActionListener(this);
// create the subscribe button
subscribeButton = new JButton(Messages.MBEANS_TAB_SUBSCRIBE_NOTIFICATIONS_BUTTON);
subscribeButton.setMnemonic(Resources.getMnemonicInt(Messages.MBEANS_TAB_SUBSCRIBE_NOTIFICATIONS_BUTTON));
subscribeButton.setToolTipText(Messages.MBEANS_TAB_SUBSCRIBE_NOTIFICATIONS_BUTTON_TOOLTIP);
subscribeButton.addActionListener(this);
// create the unsubscribe button
unsubscribeButton = new JButton(Messages.MBEANS_TAB_UNSUBSCRIBE_NOTIFICATIONS_BUTTON);
unsubscribeButton.setMnemonic(Resources.getMnemonicInt(Messages.MBEANS_TAB_UNSUBSCRIBE_NOTIFICATIONS_BUTTON));
unsubscribeButton.setToolTipText(Messages.MBEANS_TAB_UNSUBSCRIBE_NOTIFICATIONS_BUTTON_TOOLTIP);
unsubscribeButton.addActionListener(this);
// create XMBeanAttributes container
mbeanAttributes = new XMBeanAttributes(mbeansTab);
// create XMBeanOperations container
mbeanOperations = new XMBeanOperations(mbeansTab);
mbeanOperations.addOperationsListener(this);
// create XMBeanNotifications container
mbeanNotifications = new XMBeanNotifications();
mbeanNotifications.addNotificationsListener(this);
// create XMBeanInfo container
mbeanInfo = new XMBeanInfo();
}
private boolean isSelectedNode(DefaultMutableTreeNode n, DefaultMutableTreeNode cn) {
return (cn == n);
}
// Call on EDT
private void showErrorDialog(Object message, String title) {
new ThreadDialog(this, message, title, JOptionPane.ERROR_MESSAGE).run();
}
public boolean isMBeanNode(DefaultMutableTreeNode node) {
Object userObject = node.getUserObject();
if (userObject instanceof XNodeInfo) {
XNodeInfo uo = (XNodeInfo) userObject;
return uo.getType().equals(Type.MBEAN);
}
return false;
}
// Call on EDT
public synchronized void displayNode(DefaultMutableTreeNode node) {
clear();
displayEmptyNode();
if (node == null) {
return;
}
currentNode = node;
Object userObject = node.getUserObject();
if (userObject instanceof XNodeInfo) {
XNodeInfo uo = (XNodeInfo) userObject;
switch (uo.getType()) {
case MBEAN:
displayMBeanNode(node);
break;
case NONMBEAN:
displayEmptyNode();
break;
case ATTRIBUTES:
displayMBeanAttributesNode(node);
break;
case OPERATIONS:
displayMBeanOperationsNode(node);
break;
case NOTIFICATIONS:
displayMBeanNotificationsNode(node);
break;
case ATTRIBUTE:
case OPERATION:
case NOTIFICATION:
displayMetadataNode(node);
break;
default:
displayEmptyNode();
break;
}
} else {
displayEmptyNode();
}
}
// Call on EDT
private void displayMBeanNode(final DefaultMutableTreeNode node) {
final XNodeInfo uo = (XNodeInfo) node.getUserObject();
if (!uo.getType().equals(Type.MBEAN)) {
return;
}
mbean = (XMBean) uo.getData();
SwingWorker<MBeanInfo, Void> sw = new SwingWorker<MBeanInfo, Void>() {
@Override
public MBeanInfo doInBackground() throws InstanceNotFoundException,
IntrospectionException, ReflectionException, IOException {
return mbean.getMBeanInfo();
}
@Override
protected void done() {
try {
MBeanInfo mbi = get();
if (mbi != null) {
if (!isSelectedNode(node, currentNode)) {
return;
}
mbeanInfo.addMBeanInfo(mbean, mbi);
invalidate();
mainPanel.removeAll();
mainPanel.add(mbeanInfo, BorderLayout.CENTER);
southPanel.setVisible(false);
southPanel.removeAll();
validate();
repaint();
}
} catch (Exception e) {
Throwable t = Utils.getActualException(e);
if (JConsole.isDebug()) {
System.err.println("Couldn't get MBeanInfo for MBean [" +
mbean.getObjectName() + "]");
t.printStackTrace();
}
showErrorDialog(t.toString(),
Messages.PROBLEM_DISPLAYING_MBEAN);
}
}
};
sw.execute();
}
// Call on EDT
private void displayMetadataNode(final DefaultMutableTreeNode node) {
final XNodeInfo uo = (XNodeInfo) node.getUserObject();
final XMBeanInfo mbi = mbeanInfo;
switch (uo.getType()) {
case ATTRIBUTE:
SwingWorker<MBeanAttributeInfo, Void> sw =
new SwingWorker<MBeanAttributeInfo, Void>() {
@Override
public MBeanAttributeInfo doInBackground() {
Object attrData = uo.getData();
mbean = (XMBean) ((Object[]) attrData)[0];
MBeanAttributeInfo mbai =
(MBeanAttributeInfo) ((Object[]) attrData)[1];
mbeanAttributes.loadAttributes(mbean, new MBeanInfo(
null, null, new MBeanAttributeInfo[]{mbai},
null, null, null));
return mbai;
}
@Override
protected void done() {
try {
MBeanAttributeInfo mbai = get();
if (!isSelectedNode(node, currentNode)) {
return;
}
invalidate();
mainPanel.removeAll();
JPanel attributePanel =
new JPanel(new BorderLayout());
JPanel attributeBorderPanel =
new JPanel(new BorderLayout());
attributeBorderPanel.setBorder(
BorderFactory.createTitledBorder(
Messages.ATTRIBUTE_VALUE));
JPanel attributeValuePanel =
new JPanel(new BorderLayout());
attributeValuePanel.setBorder(
LineBorder.createGrayLineBorder());
attributeValuePanel.add(mbeanAttributes.getTableHeader(),
BorderLayout.PAGE_START);
attributeValuePanel.add(mbeanAttributes,
BorderLayout.CENTER);
attributeBorderPanel.add(attributeValuePanel,
BorderLayout.CENTER);
JPanel refreshButtonPanel = new JPanel();
refreshButtonPanel.add(refreshButton);
attributeBorderPanel.add(refreshButtonPanel,
BorderLayout.SOUTH);
refreshButton.setEnabled(true);
attributePanel.add(attributeBorderPanel,
BorderLayout.NORTH);
mbi.addMBeanAttributeInfo(mbai);
attributePanel.add(mbi, BorderLayout.CENTER);
mainPanel.add(attributePanel,
BorderLayout.CENTER);
southPanel.setVisible(false);
southPanel.removeAll();
validate();
repaint();
} catch (Exception e) {
Throwable t = Utils.getActualException(e);
if (JConsole.isDebug()) {
System.err.println("Problem displaying MBean " +
"attribute for MBean [" +
mbean.getObjectName() + "]");
t.printStackTrace();
}
showErrorDialog(t.toString(),
Messages.PROBLEM_DISPLAYING_MBEAN);
}
}
};
sw.execute();
break;
case OPERATION:
Object operData = uo.getData();
mbean = (XMBean) ((Object[]) operData)[0];
MBeanOperationInfo mboi =
(MBeanOperationInfo) ((Object[]) operData)[1];
mbeanOperations.loadOperations(mbean,
new MBeanInfo(null, null, null, null,
new MBeanOperationInfo[]{mboi}, null));
invalidate();
mainPanel.removeAll();
JPanel operationPanel = new JPanel(new BorderLayout());
JPanel operationBorderPanel = new JPanel(new BorderLayout());
operationBorderPanel.setBorder(BorderFactory.createTitledBorder(
Messages.OPERATION_INVOCATION));
operationBorderPanel.add(new JScrollPane(mbeanOperations));
operationPanel.add(operationBorderPanel, BorderLayout.NORTH);
mbi.addMBeanOperationInfo(mboi);
operationPanel.add(mbi, BorderLayout.CENTER);
mainPanel.add(operationPanel, BorderLayout.CENTER);
southPanel.setVisible(false);
southPanel.removeAll();
validate();
repaint();
break;
case NOTIFICATION:
Object notifData = uo.getData();
invalidate();
mainPanel.removeAll();
mbi.addMBeanNotificationInfo((MBeanNotificationInfo) notifData);
mainPanel.add(mbi, BorderLayout.CENTER);
southPanel.setVisible(false);
southPanel.removeAll();
validate();
repaint();
break;
}
}
// Call on EDT
private void displayMBeanAttributesNode(final DefaultMutableTreeNode node) {
final XNodeInfo uo = (XNodeInfo) node.getUserObject();
if (!uo.getType().equals(Type.ATTRIBUTES)) {
return;
}
mbean = (XMBean) uo.getData();
final XMBean xmb = mbean;
SwingWorker<MBeanInfo,Void> sw = new SwingWorker<MBeanInfo,Void>() {
@Override
public MBeanInfo doInBackground() throws InstanceNotFoundException,
IntrospectionException, ReflectionException, IOException {
MBeanInfo mbi = xmb.getMBeanInfo();
return mbi;
}
@Override
protected void done() {
try {
MBeanInfo mbi = get();
if (mbi != null && mbi.getAttributes() != null &&
mbi.getAttributes().length > 0) {
mbeanAttributes.loadAttributes(xmb, mbi);
if (!isSelectedNode(node, currentNode)) {
return;
}
invalidate();
mainPanel.removeAll();
JPanel borderPanel = new JPanel(new BorderLayout());
borderPanel.setBorder(BorderFactory.createTitledBorder(
Messages.ATTRIBUTE_VALUES));
borderPanel.add(new JScrollPane(mbeanAttributes));
mainPanel.add(borderPanel, BorderLayout.CENTER);
// add the refresh button to the south panel
southPanel.removeAll();
southPanel.add(refreshButton, BorderLayout.SOUTH);
southPanel.setVisible(true);
refreshButton.setEnabled(true);
validate();
repaint();
}
} catch (Exception e) {
Throwable t = Utils.getActualException(e);
if (JConsole.isDebug()) {
System.err.println("Problem displaying MBean " +
"attributes for MBean [" +
mbean.getObjectName() + "]");
t.printStackTrace();
}
showErrorDialog(t.toString(),
Messages.PROBLEM_DISPLAYING_MBEAN);
}
}
};
sw.execute();
}
// Call on EDT
private void displayMBeanOperationsNode(final DefaultMutableTreeNode node) {
final XNodeInfo uo = (XNodeInfo) node.getUserObject();
if (!uo.getType().equals(Type.OPERATIONS)) {
return;
}
mbean = (XMBean) uo.getData();
SwingWorker<MBeanInfo, Void> sw = new SwingWorker<MBeanInfo, Void>() {
@Override
public MBeanInfo doInBackground() throws InstanceNotFoundException,
IntrospectionException, ReflectionException, IOException {
return mbean.getMBeanInfo();
}
@Override
protected void done() {
try {
MBeanInfo mbi = get();
if (mbi != null) {
if (!isSelectedNode(node, currentNode)) {
return;
}
mbeanOperations.loadOperations(mbean, mbi);
invalidate();
mainPanel.removeAll();
JPanel borderPanel = new JPanel(new BorderLayout());
borderPanel.setBorder(BorderFactory.createTitledBorder(
Messages.OPERATION_INVOCATION));
borderPanel.add(new JScrollPane(mbeanOperations));
mainPanel.add(borderPanel, BorderLayout.CENTER);
southPanel.setVisible(false);
southPanel.removeAll();
validate();
repaint();
}
} catch (Exception e) {
Throwable t = Utils.getActualException(e);
if (JConsole.isDebug()) {
System.err.println("Problem displaying MBean " +
"operations for MBean [" +
mbean.getObjectName() + "]");
t.printStackTrace();
}
showErrorDialog(t.toString(),
Messages.PROBLEM_DISPLAYING_MBEAN);
}
}
};
sw.execute();
}
// Call on EDT
private void displayMBeanNotificationsNode(DefaultMutableTreeNode node) {
final XNodeInfo uo = (XNodeInfo) node.getUserObject();
if (!uo.getType().equals(Type.NOTIFICATIONS)) {
return;
}
mbean = (XMBean) uo.getData();
mbeanNotifications.loadNotifications(mbean);
updateNotifications();
invalidate();
mainPanel.removeAll();
JPanel borderPanel = new JPanel(new BorderLayout());
borderPanel.setBorder(BorderFactory.createTitledBorder(
Messages.NOTIFICATION_BUFFER));
borderPanel.add(new JScrollPane(mbeanNotifications));
mainPanel.add(borderPanel, BorderLayout.CENTER);
// add the subscribe/unsubscribe/clear buttons to the south panel
southPanel.removeAll();
southPanel.add(subscribeButton, BorderLayout.WEST);
southPanel.add(unsubscribeButton, BorderLayout.CENTER);
southPanel.add(clearButton, BorderLayout.EAST);
southPanel.setVisible(true);
subscribeButton.setEnabled(true);
unsubscribeButton.setEnabled(true);
clearButton.setEnabled(true);
validate();
repaint();
}
// Call on EDT
private void displayEmptyNode() {
invalidate();
mainPanel.removeAll();
southPanel.removeAll();
validate();
repaint();
}
/**
* Subscribe button action.
*/
private void registerListener() {
new SwingWorker<Void, Void>() {
@Override
public Void doInBackground()
throws InstanceNotFoundException, IOException {
mbeanNotifications.registerListener(currentNode);
return null;
}
@Override
protected void done() {
try {
get();
updateNotifications();
validate();
} catch (Exception e) {
Throwable t = Utils.getActualException(e);
if (JConsole.isDebug()) {
System.err.println("Problem adding listener");
t.printStackTrace();
}
showErrorDialog(t.getMessage(),
Messages.PROBLEM_ADDING_LISTENER);
}
}
}.execute();
}
/**
* Unsubscribe button action.
*/
private void unregisterListener() {
new SwingWorker<Boolean, Void>() {
@Override
public Boolean doInBackground() {
return mbeanNotifications.unregisterListener(currentNode);
}
@Override
protected void done() {
try {
if (get()) {
updateNotifications();
validate();
}
} catch (Exception e) {
Throwable t = Utils.getActualException(e);
if (JConsole.isDebug()) {
System.err.println("Problem removing listener");
t.printStackTrace();
}
showErrorDialog(t.getMessage(),
Messages.PROBLEM_REMOVING_LISTENER);
}
}
}.execute();
}
/**
* Refresh button action.
*/
private void refreshAttributes() {
mbeanAttributes.refreshAttributes();
}
// Call on EDT
private void updateNotifications() {
if (mbeanNotifications.isListenerRegistered(mbean)) {
long received = mbeanNotifications.getReceivedNotifications(mbean);
updateReceivedNotifications(currentNode, received, false);
} else {
clearNotifications();
}
}
/**
* Update notification node label in MBean tree: "Notifications[received]".
*/
// Call on EDT
private void updateReceivedNotifications(
DefaultMutableTreeNode emitter, long received, boolean bold) {
String text = Messages.NOTIFICATIONS + "[" + received + "]";
DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) mbeansTab.getTree().getLastSelectedPathComponent();
if (bold && emitter != selectedNode) {
text = "<html><b>" + text + "</b></html>";
}
updateNotificationsNodeLabel(emitter, text);
}
/**
* Update notification node label in MBean tree: "Notifications".
*/
// Call on EDT
private void clearNotifications() {
updateNotificationsNodeLabel(currentNode,
Messages.NOTIFICATIONS);
}
/**
* Update notification node label in MBean tree: "Notifications[0]".
*/
// Call on EDT
private void clearNotifications0() {
updateNotificationsNodeLabel(currentNode,
Messages.NOTIFICATIONS + "[0]");
}
/**
* Update the label of the supplied MBean tree node.
*/
// Call on EDT
private void updateNotificationsNodeLabel(
DefaultMutableTreeNode node, String label) {
synchronized (mbeansTab.getTree()) {
invalidate();
XNodeInfo oldUserObject = (XNodeInfo) node.getUserObject();
XNodeInfo newUserObject = new XNodeInfo(
oldUserObject.getType(), oldUserObject.getData(),
label, oldUserObject.getToolTipText());
node.setUserObject(newUserObject);
DefaultTreeModel model =
(DefaultTreeModel) mbeansTab.getTree().getModel();
model.nodeChanged(node);
validate();
repaint();
}
}
/**
* Clear button action.
*/
// Call on EDT
private void clearCurrentNotifications() {
mbeanNotifications.clearCurrentNotifications();
if (mbeanNotifications.isListenerRegistered(mbean)) {
// Update notifs in MBean tree "Notifications[0]".
//
// Notification buffer has been cleared with a listener been
// registered so add "[0]" at the end of the node label.
//
clearNotifications0();
} else {
// Update notifs in MBean tree "Notifications".
//
// Notification buffer has been cleared without a listener been
// registered so don't add "[0]" at the end of the node label.
//
clearNotifications();
}
}
// Call on EDT
private void clear() {
mbeanAttributes.stopCellEditing();
mbeanAttributes.emptyTable();
mbeanAttributes.removeAttributes();
mbeanOperations.removeOperations();
mbeanNotifications.stopCellEditing();
mbeanNotifications.emptyTable();
mbeanNotifications.disableNotifications();
mbean = null;
currentNode = null;
}
/**
* Notification listener: handles asynchronous reception
* of MBean operation results and MBean notifications.
*/
// Call on EDT
public void handleNotification(Notification e, Object handback) {
// Operation result
if (e.getType().equals(XOperations.OPERATION_INVOCATION_EVENT)) {
final Object message;
if (handback == null) {
JTextArea textArea = new JTextArea("null");
textArea.setEditable(false);
textArea.setEnabled(true);
textArea.setRows(textArea.getLineCount());
message = textArea;
} else {
Component comp = mbeansTab.getDataViewer().
createOperationViewer(handback, mbean);
if (comp == null) {
JTextArea textArea = new JTextArea(handback.toString());
textArea.setEditable(false);
textArea.setEnabled(true);
textArea.setRows(textArea.getLineCount());
JScrollPane scrollPane = new JScrollPane(textArea);
Dimension d = scrollPane.getPreferredSize();
if (d.getWidth() > 400 || d.getHeight() > 250) {
scrollPane.setPreferredSize(new Dimension(400, 250));
}
message = scrollPane;
} else {
if (!(comp instanceof JScrollPane)) {
comp = new JScrollPane(comp);
}
Dimension d = comp.getPreferredSize();
if (d.getWidth() > 400 || d.getHeight() > 250) {
comp.setPreferredSize(new Dimension(400, 250));
}
message = comp;
}
}
new ThreadDialog(
(Component) e.getSource(),
message,
Messages.OPERATION_RETURN_VALUE,
JOptionPane.INFORMATION_MESSAGE).run();
} // Got notification
else if (e.getType().equals(
XMBeanNotifications.NOTIFICATION_RECEIVED_EVENT)) {
DefaultMutableTreeNode emitter = (DefaultMutableTreeNode) handback;
Long received = (Long) e.getUserData();
updateReceivedNotifications(emitter, received.longValue(), true);
}
}
/**
* Action listener: handles actions in panel buttons
*/
// Call on EDT
public void actionPerformed(ActionEvent e) {
if (e.getSource() instanceof JButton) {
JButton button = (JButton) e.getSource();
// Refresh button
if (button == refreshButton) {
refreshAttributes();
return;
}
// Clear button
if (button == clearButton) {
clearCurrentNotifications();
return;
}
// Subscribe button
if (button == subscribeButton) {
registerListener();
return;
}
// Unsubscribe button
if (button == unsubscribeButton) {
unregisterListener();
return;
}
}
}
}

View File

@@ -0,0 +1,180 @@
/*
* Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.jconsole.inspector;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
public abstract class XTable extends JTable {
static final int NAME_COLUMN = 0;
static final int VALUE_COLUMN = 1;
private Color defaultColor, editableColor, errorColor;
private Font normalFont, boldFont;
public XTable () {
super();
@SuppressWarnings("serial")
final TableSorter sorter = new TableSorter();
setModel(sorter);
sorter.addMouseListenerToHeaderInTable(this);
setRowSelectionAllowed(false);
setColumnSelectionAllowed(false);
setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
}
Color getDefaultColor() {
return defaultColor;
}
Color getEditableColor() {
return editableColor;
}
/**
* Called by TableSorter if a mouse event requests to sort the rows.
* @param column the column against which the rows are sorted
*/
void sortRequested(int column) {
// This is a hook for subclasses
}
/**
* This returns the select index as the table was at initialization
*/
public int getSelectedIndex() {
return convertRowToIndex(getSelectedRow());
}
/*
* Converts the row into index (before sorting)
*/
public int convertRowToIndex(int row) {
if (row == -1) return row;
if (getModel() instanceof TableSorter) {
return ((TableSorter) getModel()).getIndexOfRow(row);
} else {
return row;
}
}
public void emptyTable() {
DefaultTableModel model = (DefaultTableModel)getModel();
while (model.getRowCount()>0)
model.removeRow(0);
}
public abstract boolean isTableEditable();
public abstract boolean isColumnEditable(int column);
public abstract boolean isReadable(int row);
public abstract boolean isWritable(int row);
public abstract boolean isCellError(int row, int col);
public abstract boolean isAttributeViewable(int row, int col);
public abstract void setTableValue(Object value,int row);
public abstract Object getValue(int row);
public abstract String getClassName(int row);
public abstract String getValueName(int row);
public boolean isReadWrite(int row) {
return (isReadable(row) && isWritable(row));
}
//JTable re-implementation
//attribute can be editable even if unavailable
@Override
public boolean isCellEditable(int row, int col) {
return ((isTableEditable() && isColumnEditable(col)
&& isWritable(row)
&& Utils.isEditableType(getClassName(row))));
}
//attribute can be droppable even if unavailable
public boolean isCellDroppable(int row, int col) {
return (isTableEditable() && isColumnEditable(col)
&& isWritable(row));
}
//returns null, means no tool tip
public String getToolTip(int row, int column) {
return null;
}
/**
* This method sets read write rows to be blue, and other rows to be their
* default rendered colour.
*/
@Override
public TableCellRenderer getCellRenderer(int row, int column) {
DefaultTableCellRenderer tcr =
(DefaultTableCellRenderer) super.getCellRenderer(row,column);
tcr.setToolTipText(getToolTip(row,column));
if (defaultColor == null) {
defaultColor = tcr.getForeground();
editableColor = Color.blue;
errorColor = Color.red;
// this sometimes happens for some reason
if (defaultColor == null) {
return tcr;
}
}
if (column != VALUE_COLUMN) {
tcr.setForeground(defaultColor);
return tcr;
}
if (isCellError(row,column)) {
tcr.setForeground(errorColor);
} else if (isCellEditable(row, column)) {
tcr.setForeground(editableColor);
} else {
tcr.setForeground(defaultColor);
}
return tcr;
}
@Override
public Component prepareRenderer(TableCellRenderer renderer,
int row, int column) {
Component comp = super.prepareRenderer(renderer, row, column);
if (normalFont == null) {
normalFont = comp.getFont();
boldFont = normalFont.deriveFont(Font.BOLD);
}
if (column == VALUE_COLUMN && isAttributeViewable(row, VALUE_COLUMN)) {
comp.setFont(boldFont);
} else {
comp.setFont(normalFont);
}
return comp;
}
}

View File

@@ -0,0 +1,201 @@
/*
* Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.jconsole.inspector;
import java.awt.*;
import java.awt.event.*;
import javax.swing.event.*;
import javax.swing.*;
/**
* This list implements the drag and drop functionality.
*/
@SuppressWarnings("serial")
public class XTextField extends JPanel
implements DocumentListener,
ActionListener {
private XObject selectedObject;
protected JTextField textField;
private static boolean allowNullSelection = false;
protected final static int COMPATIBLE_VALUE = 1;
protected final static int CURRENT_VALUE = 2;
protected final static int NULL_VALUE = 3;
private JButton button;
private XOperations operation;
//used in XTestFieldEditor
public XTextField() {
super(new BorderLayout());
add(textField = new JTextField(),BorderLayout.CENTER);
textField.addActionListener(this);
//
}
public XTextField(Object value) {
this(value,value.toString().length());
}
public XTextField(Object value, int colWidth) {
this(value,value.getClass(),colWidth, true, null, null);
}
public XTextField(Object value,
Class<?> expectedClass,
int colWidth,
boolean isCallable,
JButton button,
XOperations operation) {
super(new BorderLayout());
this.button = button;
this.operation = operation;
add(textField = new JTextField(value.toString(),colWidth),
BorderLayout.CENTER);
if(isCallable)
textField.addActionListener(this);
boolean fieldEditable = Utils.isEditableType(expectedClass.getName());
if (fieldEditable && isCallable) {
textField.setEditable(true);
}
else {
textField.setEditable(false);
}
}
public static void setNullSelectionAllowed(boolean allowNullSelection) {
XTextField.allowNullSelection = allowNullSelection;
}
public static boolean getNullSelectionAllowed() {
return allowNullSelection;
}
protected void init(Object value, Class<?> expectedClass) {
boolean fieldEditable = Utils.isEditableType(expectedClass.getName());
clearObject();
if (value != null) {
textField.setText(value.toString());
}
else {
//null String value for the moment
textField.setText("");
}
textField.setToolTipText(null);
if (fieldEditable) {
if (!textField.isEditable()) {
textField.setEditable(true);
}
}
else {
if (textField.isEditable()) {
textField.setEditable(false);
}
}
}
private synchronized void clearObject() {
textField.getDocument().removeDocumentListener(this);
selectedObject = null;
setDefaultColors();
}
private synchronized void setDefaultColors() {
// if (fore != null) textField.setForeground(fore);
// if (back != null) textField.setBackground(back);
}
public void setHorizontalAlignment(int h) {
textField.setHorizontalAlignment(h);
}
//can be overwritten
protected JMenuItem buildJMenuItem(XObject xobject, int valueType) {
if (valueType == COMPATIBLE_VALUE) {
return new JMenuItem(xobject.getText());
}
else if (valueType == CURRENT_VALUE) {
return new JMenuItem("> "+xobject.getText());
}
else if (valueType == NULL_VALUE) {
return new JMenuItem("null");
}
else {
return null;
}
}
// ACTIONLISTENER IMPLEMENTATION
public void actionPerformed(ActionEvent e) {
if (e.getSource() instanceof JTextField) {
if(operation != null)
operation.performInvokeRequest(button);
}
}
/**
* This method returns either the user inputted String, or an XObject
* if one was dropped on the input field.
*/
public Object getValue() {
if (selectedObject!=null) {
if (selectedObject == XObject.NULL_OBJECT) {
//null case
return null;
}
else {
return selectedObject;
}
}
else {
return textField.getText();
}
}
public void changedUpdate(DocumentEvent e) {
// the user typed something, so remove references
// to the object that was dropped.
clearObject();
}
public void removeUpdate(DocumentEvent e) {
// the user typed something, so remove references
// to the object that was dropped.
clearObject();
}
public void insertUpdate(DocumentEvent e) {
// the user typed something, so remove references
// to the object that was dropped.
clearObject();
}
}

View File

@@ -0,0 +1,156 @@
/*
* Copyright (c) 2004, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.jconsole.inspector;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.util.EventObject;
import javax.swing.JMenuItem;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.EventListenerList;
import javax.swing.table.TableCellEditor;
@SuppressWarnings("serial")
public class XTextFieldEditor extends XTextField implements TableCellEditor {
protected EventListenerList evtListenerList = new EventListenerList();
protected ChangeEvent changeEvent = new ChangeEvent(this);
private FocusListener editorFocusListener = new FocusAdapter() {
@Override
public void focusLost(FocusEvent e) {
// fireEditingStopped();
// must not call fireEditingStopped() here!
}
};
public XTextFieldEditor() {
super();
textField.addFocusListener(editorFocusListener);
}
//edition stopped ou JMenuItem selection & JTextField selection
@Override
public void actionPerformed(ActionEvent e) {
super.actionPerformed(e);
if ((e.getSource() instanceof JMenuItem) ||
(e.getSource() instanceof JTextField)) {
fireEditingStopped();
}
}
//edition stopped on drag & drop success
protected void dropSuccess() {
fireEditingStopped();
}
//TableCellEditor implementation
public void addCellEditorListener(CellEditorListener listener) {
evtListenerList.add(CellEditorListener.class,listener);
}
public void removeCellEditorListener(CellEditorListener listener) {
evtListenerList.remove(CellEditorListener.class, listener);
}
protected void fireEditingStopped() {
CellEditorListener listener;
Object[] listeners = evtListenerList.getListenerList();
for (int i=0;i< listeners.length;i++) {
if (listeners[i] == CellEditorListener.class) {
listener = (CellEditorListener) listeners[i+1];
listener.editingStopped(changeEvent);
}
}
}
protected void fireEditingCanceled() {
CellEditorListener listener;
Object[] listeners = evtListenerList.getListenerList();
for (int i=0;i< listeners.length;i++) {
if (listeners[i] == CellEditorListener.class) {
listener = (CellEditorListener) listeners[i+1];
listener.editingCanceled(changeEvent);
}
}
}
public void cancelCellEditing() {
fireEditingCanceled();
}
public boolean stopCellEditing() {
fireEditingStopped();
return true;
}
public boolean isCellEditable(EventObject event) {
return true;
}
public boolean shouldSelectCell(EventObject event) {
return true;
}
public Object getCellEditorValue() {
Object object = getValue();
if (object instanceof XObject) {
return ((XObject) object).getObject();
}
else {
return object;
}
}
public Component getTableCellEditorComponent(JTable table,
Object value,
boolean isSelected,
int row,
int column) {
String className;
if (table instanceof XTable) {
XTable mytable = (XTable) table;
className = mytable.getClassName(row);
} else {
className = String.class.getName();
}
try {
init(value,Utils.getClass(className));
}
catch(Exception e) {}
return this;
}
}

View File

@@ -0,0 +1,834 @@
/*
* Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.jconsole.inspector;
import java.io.IOException;
import java.util.*;
import javax.management.*;
import javax.swing.*;
import javax.swing.tree.*;
import sun.tools.jconsole.JConsole;
import sun.tools.jconsole.MBeansTab;
import sun.tools.jconsole.Messages;
import sun.tools.jconsole.inspector.XNodeInfo;
import static sun.tools.jconsole.inspector.XNodeInfo.Type;
@SuppressWarnings("serial")
public class XTree extends JTree {
private static final List<String> orderedKeyPropertyList =
new ArrayList<String>();
static {
String keyPropertyList =
System.getProperty("com.sun.tools.jconsole.mbeans.keyPropertyList");
if (keyPropertyList == null) {
orderedKeyPropertyList.add("type");
orderedKeyPropertyList.add("j2eeType");
} else {
StringTokenizer st = new StringTokenizer(keyPropertyList, ",");
while (st.hasMoreTokens()) {
orderedKeyPropertyList.add(st.nextToken());
}
}
}
private MBeansTab mbeansTab;
private Map<String, DefaultMutableTreeNode> nodes =
new HashMap<String, DefaultMutableTreeNode>();
public XTree(MBeansTab mbeansTab) {
this(new DefaultMutableTreeNode("MBeanTreeRootNode"), mbeansTab);
}
public XTree(TreeNode root, MBeansTab mbeansTab) {
super(root, true);
this.mbeansTab = mbeansTab;
setRootVisible(false);
setShowsRootHandles(true);
ToolTipManager.sharedInstance().registerComponent(this);
}
/**
* This method removes the node from its parent
*/
// Call on EDT
private synchronized void removeChildNode(DefaultMutableTreeNode child) {
DefaultTreeModel model = (DefaultTreeModel) getModel();
model.removeNodeFromParent(child);
}
/**
* This method adds the child to the specified parent node
* at specific index.
*/
// Call on EDT
private synchronized void addChildNode(
DefaultMutableTreeNode parent,
DefaultMutableTreeNode child,
int index) {
DefaultTreeModel model = (DefaultTreeModel) getModel();
model.insertNodeInto(child, parent, index);
}
/**
* This method adds the child to the specified parent node.
* The index where the child is to be added depends on the
* child node being Comparable or not. If the child node is
* not Comparable then it is added at the end, i.e. right
* after the current parent's children.
*/
// Call on EDT
private synchronized void addChildNode(
DefaultMutableTreeNode parent, DefaultMutableTreeNode child) {
int childCount = parent.getChildCount();
if (childCount == 0) {
addChildNode(parent, child, 0);
return;
}
if (child instanceof ComparableDefaultMutableTreeNode) {
ComparableDefaultMutableTreeNode comparableChild =
(ComparableDefaultMutableTreeNode) child;
for (int i = childCount - 1; i >= 0; i--) {
DefaultMutableTreeNode brother =
(DefaultMutableTreeNode) parent.getChildAt(i);
// expr1: child node must be inserted after metadata nodes
// - OR -
// expr2: "child >= brother"
if ((i <= 2 && isMetadataNode(brother)) ||
comparableChild.compareTo(brother) >= 0) {
addChildNode(parent, child, i + 1);
return;
}
}
// "child < all brothers", add at the beginning
addChildNode(parent, child, 0);
return;
}
// "child not comparable", add at the end
addChildNode(parent, child, childCount);
}
/**
* This method removes all the displayed nodes from the tree,
* but does not affect actual MBeanServer contents.
*/
// Call on EDT
@Override
public synchronized void removeAll() {
DefaultTreeModel model = (DefaultTreeModel) getModel();
DefaultMutableTreeNode root = (DefaultMutableTreeNode) model.getRoot();
root.removeAllChildren();
model.nodeStructureChanged(root);
nodes.clear();
}
// Call on EDT
public synchronized void removeMBeanFromView(ObjectName mbean) {
// We assume here that MBeans are removed one by one (on MBean
// unregistered notification). Deletes the tree node associated
// with the given MBean and recursively all the node parents
// which are leaves and non XMBean.
//
DefaultMutableTreeNode node = null;
Dn dn = new Dn(mbean);
if (dn.getTokenCount() > 0) {
DefaultTreeModel model = (DefaultTreeModel) getModel();
Token token = dn.getToken(0);
String hashKey = dn.getHashKey(token);
node = nodes.get(hashKey);
if ((node != null) && (!node.isRoot())) {
if (hasNonMetadataNodes(node)) {
removeMetadataNodes(node);
String label = token.getValue();
XNodeInfo userObject = new XNodeInfo(
Type.NONMBEAN, label,
label, token.getTokenValue());
changeNodeValue(node, userObject);
} else {
DefaultMutableTreeNode parent =
(DefaultMutableTreeNode) node.getParent();
model.removeNodeFromParent(node);
nodes.remove(hashKey);
removeParentFromView(dn, 1, parent);
}
}
}
}
/**
* Returns true if any of the children nodes is a non MBean metadata node.
*/
private boolean hasNonMetadataNodes(DefaultMutableTreeNode node) {
for (Enumeration<?> e = node.children(); e.hasMoreElements();) {
DefaultMutableTreeNode n = (DefaultMutableTreeNode) e.nextElement();
Object uo = n.getUserObject();
if (uo instanceof XNodeInfo) {
switch (((XNodeInfo) uo).getType()) {
case ATTRIBUTES:
case NOTIFICATIONS:
case OPERATIONS:
break;
default:
return true;
}
} else {
return true;
}
}
return false;
}
/**
* Returns true if any of the children nodes is an MBean metadata node.
*/
public boolean hasMetadataNodes(DefaultMutableTreeNode node) {
for (Enumeration<?> e = node.children(); e.hasMoreElements();) {
DefaultMutableTreeNode n = (DefaultMutableTreeNode) e.nextElement();
Object uo = n.getUserObject();
if (uo instanceof XNodeInfo) {
switch (((XNodeInfo) uo).getType()) {
case ATTRIBUTES:
case NOTIFICATIONS:
case OPERATIONS:
return true;
default:
break;
}
} else {
return false;
}
}
return false;
}
/**
* Returns true if the given node is an MBean metadata node.
*/
public boolean isMetadataNode(DefaultMutableTreeNode node) {
Object uo = node.getUserObject();
if (uo instanceof XNodeInfo) {
switch (((XNodeInfo) uo).getType()) {
case ATTRIBUTES:
case NOTIFICATIONS:
case OPERATIONS:
return true;
default:
return false;
}
} else {
return false;
}
}
/**
* Remove the metadata nodes associated with a given MBean node.
*/
// Call on EDT
private void removeMetadataNodes(DefaultMutableTreeNode node) {
Set<DefaultMutableTreeNode> metadataNodes =
new HashSet<DefaultMutableTreeNode>();
DefaultTreeModel model = (DefaultTreeModel) getModel();
for (Enumeration<?> e = node.children(); e.hasMoreElements();) {
DefaultMutableTreeNode n = (DefaultMutableTreeNode) e.nextElement();
Object uo = n.getUserObject();
if (uo instanceof XNodeInfo) {
switch (((XNodeInfo) uo).getType()) {
case ATTRIBUTES:
case NOTIFICATIONS:
case OPERATIONS:
metadataNodes.add(n);
break;
default:
break;
}
}
}
for (DefaultMutableTreeNode n : metadataNodes) {
model.removeNodeFromParent(n);
}
}
/**
* Removes only the parent nodes which are non MBean and leaf.
* This method assumes the child nodes have been removed before.
*/
// Call on EDT
private DefaultMutableTreeNode removeParentFromView(
Dn dn, int index, DefaultMutableTreeNode node) {
if ((!node.isRoot()) && node.isLeaf() &&
(!(((XNodeInfo) node.getUserObject()).getType().equals(Type.MBEAN)))) {
DefaultMutableTreeNode parent =
(DefaultMutableTreeNode) node.getParent();
removeChildNode(node);
String hashKey = dn.getHashKey(dn.getToken(index));
nodes.remove(hashKey);
removeParentFromView(dn, index + 1, parent);
}
return node;
}
// Call on EDT
public synchronized void addMBeansToView(Set<ObjectName> mbeans) {
Set<Dn> dns = new TreeSet<Dn>();
for (ObjectName mbean : mbeans) {
Dn dn = new Dn(mbean);
dns.add(dn);
}
for (Dn dn : dns) {
ObjectName mbean = dn.getObjectName();
XMBean xmbean = new XMBean(mbean, mbeansTab);
addMBeanToView(mbean, xmbean, dn);
}
}
// Call on EDT
public synchronized void addMBeanToView(ObjectName mbean) {
// Build XMBean for the given MBean
//
XMBean xmbean = new XMBean(mbean, mbeansTab);
// Build Dn for the given MBean
//
Dn dn = new Dn(mbean);
// Add the new nodes to the MBean tree from leaf to root
//
addMBeanToView(mbean, xmbean, dn);
}
// Call on EDT
private synchronized void addMBeanToView(
ObjectName mbean, XMBean xmbean, Dn dn) {
DefaultMutableTreeNode childNode = null;
DefaultMutableTreeNode parentNode = null;
// Add the node or replace its user object if already added
//
Token token = dn.getToken(0);
String hashKey = dn.getHashKey(token);
if (nodes.containsKey(hashKey)) {
// Found existing node previously created when adding another node
//
childNode = nodes.get(hashKey);
// Replace user object to reflect that this node is an MBean
//
Object data = createNodeValue(xmbean, token);
String label = data.toString();
XNodeInfo userObject =
new XNodeInfo(Type.MBEAN, data, label, mbean.toString());
changeNodeValue(childNode, userObject);
return;
}
// Create new leaf node
//
childNode = createDnNode(dn, token, xmbean);
nodes.put(hashKey, childNode);
// Add intermediate non MBean nodes
//
for (int i = 1; i < dn.getTokenCount(); i++) {
token = dn.getToken(i);
hashKey = dn.getHashKey(token);
if (nodes.containsKey(hashKey)) {
// Intermediate node already present, add new node as child
//
parentNode = nodes.get(hashKey);
addChildNode(parentNode, childNode);
return;
} else {
// Create new intermediate node
//
if ("domain".equals(token.getTokenType())) {
parentNode = createDomainNode(dn, token);
DefaultMutableTreeNode root =
(DefaultMutableTreeNode) getModel().getRoot();
addChildNode(root, parentNode);
} else {
parentNode = createSubDnNode(dn, token);
}
nodes.put(hashKey, parentNode);
addChildNode(parentNode, childNode);
}
childNode = parentNode;
}
}
// Call on EDT
private synchronized void changeNodeValue(
DefaultMutableTreeNode node, XNodeInfo nodeValue) {
if (node instanceof ComparableDefaultMutableTreeNode) {
// should it stay at the same place?
DefaultMutableTreeNode clone =
(DefaultMutableTreeNode) node.clone();
clone.setUserObject(nodeValue);
if (((ComparableDefaultMutableTreeNode) node).compareTo(clone) == 0) {
// the order in the tree didn't change
node.setUserObject(nodeValue);
DefaultTreeModel model = (DefaultTreeModel) getModel();
model.nodeChanged(node);
} else {
// delete the node and re-order it in case the
// node value modifies the order in the tree
DefaultMutableTreeNode parent =
(DefaultMutableTreeNode) node.getParent();
removeChildNode(node);
node.setUserObject(nodeValue);
addChildNode(parent, node);
}
} else {
// not comparable stays at the same place
node.setUserObject(nodeValue);
DefaultTreeModel model = (DefaultTreeModel) getModel();
model.nodeChanged(node);
}
// Load the MBean metadata if type is MBEAN
if (nodeValue.getType().equals(Type.MBEAN)) {
removeMetadataNodes(node);
TreeNode[] treeNodes = node.getPath();
TreePath path = new TreePath(treeNodes);
if (isExpanded(path)) {
addMetadataNodes(node);
}
}
// Clear the current selection and set it
// again so valueChanged() gets called
if (node == getLastSelectedPathComponent()) {
TreePath selectionPath = getSelectionPath();
clearSelection();
setSelectionPath(selectionPath);
}
}
/**
* Creates the domain node.
*/
private DefaultMutableTreeNode createDomainNode(Dn dn, Token token) {
DefaultMutableTreeNode node = new ComparableDefaultMutableTreeNode();
String label = dn.getDomain();
XNodeInfo userObject =
new XNodeInfo(Type.NONMBEAN, label, label, label);
node.setUserObject(userObject);
return node;
}
/**
* Creates the node corresponding to the whole Dn, i.e. an MBean.
*/
private DefaultMutableTreeNode createDnNode(
Dn dn, Token token, XMBean xmbean) {
DefaultMutableTreeNode node = new ComparableDefaultMutableTreeNode();
Object data = createNodeValue(xmbean, token);
String label = data.toString();
XNodeInfo userObject = new XNodeInfo(Type.MBEAN, data, label,
xmbean.getObjectName().toString());
node.setUserObject(userObject);
return node;
}
/**
* Creates the node corresponding to a subDn, i.e. a non-MBean
* intermediate node.
*/
private DefaultMutableTreeNode createSubDnNode(Dn dn, Token token) {
DefaultMutableTreeNode node = new ComparableDefaultMutableTreeNode();
String label = isKeyValueView() ? token.getTokenValue() : token.getValue();
XNodeInfo userObject =
new XNodeInfo(Type.NONMBEAN, label, label, token.getTokenValue());
node.setUserObject(userObject);
return node;
}
private Object createNodeValue(XMBean xmbean, Token token) {
String label = isKeyValueView() ? token.getTokenValue() : token.getValue();
xmbean.setText(label);
return xmbean;
}
/**
* Parses the MBean ObjectName comma-separated properties string and puts
* the individual key/value pairs into the map. Key order in the properties
* string is preserved by the map.
*/
private static Map<String, String> extractKeyValuePairs(
String props, ObjectName mbean) {
Map<String, String> map = new LinkedHashMap<String, String>();
int eq = props.indexOf("=");
while (eq != -1) {
String key = props.substring(0, eq);
String value = mbean.getKeyProperty(key);
map.put(key, value);
props = props.substring(key.length() + 1 + value.length());
if (props.startsWith(",")) {
props = props.substring(1);
}
eq = props.indexOf("=");
}
return map;
}
/**
* Returns the ordered key property list that will be used to build the
* MBean tree. If the "com.sun.tools.jconsole.mbeans.keyPropertyList" system
* property is not specified, then the ordered key property list used
* to build the MBean tree will be the one returned by the method
* ObjectName.getKeyPropertyListString() with "type" as first key,
* and "j2eeType" as second key, if present. If any of the keys specified
* in the comma-separated key property list does not apply to the given
* MBean then it will be discarded.
*/
private static String getKeyPropertyListString(ObjectName mbean) {
String props = mbean.getKeyPropertyListString();
Map<String, String> map = extractKeyValuePairs(props, mbean);
StringBuilder sb = new StringBuilder();
// Add the key/value pairs to the buffer following the
// key order defined by the "orderedKeyPropertyList"
for (String key : orderedKeyPropertyList) {
if (map.containsKey(key)) {
sb.append(key + "=" + map.get(key) + ",");
map.remove(key);
}
}
// Add the remaining key/value pairs to the buffer
for (Map.Entry<String, String> entry : map.entrySet()) {
sb.append(entry.getKey() + "=" + entry.getValue() + ",");
}
String orderedKeyPropertyListString = sb.toString();
orderedKeyPropertyListString = orderedKeyPropertyListString.substring(
0, orderedKeyPropertyListString.length() - 1);
return orderedKeyPropertyListString;
}
// Call on EDT
public void addMetadataNodes(DefaultMutableTreeNode node) {
XMBean mbean = (XMBean) ((XNodeInfo) node.getUserObject()).getData();
DefaultTreeModel model = (DefaultTreeModel) getModel();
MBeanInfoNodesSwingWorker sw =
new MBeanInfoNodesSwingWorker(model, node, mbean);
if (sw != null) {
sw.execute();
}
}
private static class MBeanInfoNodesSwingWorker
extends SwingWorker<Object[], Void> {
private final DefaultTreeModel model;
private final DefaultMutableTreeNode node;
private final XMBean mbean;
public MBeanInfoNodesSwingWorker(
DefaultTreeModel model,
DefaultMutableTreeNode node,
XMBean mbean) {
this.model = model;
this.node = node;
this.mbean = mbean;
}
@Override
public Object[] doInBackground() throws InstanceNotFoundException,
IntrospectionException, ReflectionException, IOException {
Object result[] = new Object[2];
// Retrieve MBeanInfo for this MBean
result[0] = mbean.getMBeanInfo();
// Check if this MBean is a notification emitter
result[1] = mbean.isBroadcaster();
return result;
}
@Override
protected void done() {
try {
Object result[] = get();
MBeanInfo mbeanInfo = (MBeanInfo) result[0];
Boolean isBroadcaster = (Boolean) result[1];
if (mbeanInfo != null) {
addMBeanInfoNodes(model, node, mbean, mbeanInfo, isBroadcaster);
}
} catch (Exception e) {
Throwable t = Utils.getActualException(e);
if (JConsole.isDebug()) {
t.printStackTrace();
}
}
}
// Call on EDT
private void addMBeanInfoNodes(
DefaultTreeModel tree, DefaultMutableTreeNode node,
XMBean mbean, MBeanInfo mbeanInfo, Boolean isBroadcaster) {
MBeanAttributeInfo[] ai = mbeanInfo.getAttributes();
MBeanOperationInfo[] oi = mbeanInfo.getOperations();
MBeanNotificationInfo[] ni = mbeanInfo.getNotifications();
// Insert the Attributes/Operations/Notifications metadata nodes as
// the three first children of this MBean node. This is only useful
// when this MBean node denotes an MBean but it's not a leaf in the
// MBean tree
//
int childIndex = 0;
// MBeanAttributeInfo node
//
if (ai != null && ai.length > 0) {
DefaultMutableTreeNode attributes = new DefaultMutableTreeNode();
XNodeInfo attributesUO = new XNodeInfo(Type.ATTRIBUTES, mbean,
Messages.ATTRIBUTES, null);
attributes.setUserObject(attributesUO);
node.insert(attributes, childIndex++);
for (MBeanAttributeInfo mbai : ai) {
DefaultMutableTreeNode attribute = new DefaultMutableTreeNode();
XNodeInfo attributeUO = new XNodeInfo(Type.ATTRIBUTE,
new Object[]{mbean, mbai}, mbai.getName(), null);
attribute.setUserObject(attributeUO);
attribute.setAllowsChildren(false);
attributes.add(attribute);
}
}
// MBeanOperationInfo node
//
if (oi != null && oi.length > 0) {
DefaultMutableTreeNode operations = new DefaultMutableTreeNode();
XNodeInfo operationsUO = new XNodeInfo(Type.OPERATIONS, mbean,
Messages.OPERATIONS, null);
operations.setUserObject(operationsUO);
node.insert(operations, childIndex++);
for (MBeanOperationInfo mboi : oi) {
// Compute the operation's tool tip text:
// "operationname(param1type,param2type,...)"
//
StringBuilder sb = new StringBuilder();
for (MBeanParameterInfo mbpi : mboi.getSignature()) {
sb.append(mbpi.getType() + ",");
}
String signature = sb.toString();
if (signature.length() > 0) {
// Remove the trailing ','
//
signature = signature.substring(0, signature.length() - 1);
}
String toolTipText = mboi.getName() + "(" + signature + ")";
// Create operation node
//
DefaultMutableTreeNode operation = new DefaultMutableTreeNode();
XNodeInfo operationUO = new XNodeInfo(Type.OPERATION,
new Object[]{mbean, mboi}, mboi.getName(), toolTipText);
operation.setUserObject(operationUO);
operation.setAllowsChildren(false);
operations.add(operation);
}
}
// MBeanNotificationInfo node
//
if (isBroadcaster != null && isBroadcaster.booleanValue()) {
DefaultMutableTreeNode notifications = new DefaultMutableTreeNode();
XNodeInfo notificationsUO = new XNodeInfo(Type.NOTIFICATIONS, mbean,
Messages.NOTIFICATIONS, null);
notifications.setUserObject(notificationsUO);
node.insert(notifications, childIndex++);
if (ni != null && ni.length > 0) {
for (MBeanNotificationInfo mbni : ni) {
DefaultMutableTreeNode notification =
new DefaultMutableTreeNode();
XNodeInfo notificationUO = new XNodeInfo(Type.NOTIFICATION,
mbni, mbni.getName(), null);
notification.setUserObject(notificationUO);
notification.setAllowsChildren(false);
notifications.add(notification);
}
}
}
// Update tree model
//
model.reload(node);
}
}
//
// Tree preferences
//
private static boolean treeView;
private static boolean treeViewInit = false;
private static boolean isTreeView() {
if (!treeViewInit) {
treeView = getTreeViewValue();
treeViewInit = true;
}
return treeView;
}
private static boolean getTreeViewValue() {
String tv = System.getProperty("treeView");
return ((tv == null) ? true : !(tv.equals("false")));
}
//
// MBean key-value preferences
//
private boolean keyValueView = Boolean.getBoolean("keyValueView");
private boolean isKeyValueView() {
return keyValueView;
}
//
// Utility classes
//
private static class ComparableDefaultMutableTreeNode
extends DefaultMutableTreeNode
implements Comparable<DefaultMutableTreeNode> {
public int compareTo(DefaultMutableTreeNode node) {
return (this.toString().compareTo(node.toString()));
}
}
private static class Dn implements Comparable<Dn> {
private ObjectName mbean;
private String domain;
private String keyPropertyList;
private String hashDn;
private List<Token> tokens = new ArrayList<Token>();
public Dn(ObjectName mbean) {
this.mbean = mbean;
this.domain = mbean.getDomain();
this.keyPropertyList = getKeyPropertyListString(mbean);
if (isTreeView()) {
// Tree view
Map<String, String> map =
extractKeyValuePairs(keyPropertyList, mbean);
for (Map.Entry<String, String> entry : map.entrySet()) {
tokens.add(new Token("key", entry.getKey() + "=" + entry.getValue()));
}
} else {
// Flat view
tokens.add(new Token("key", "properties=" + keyPropertyList));
}
// Add the domain as the first token in the Dn
tokens.add(0, new Token("domain", "domain=" + domain));
// Reverse the Dn (from leaf to root)
Collections.reverse(tokens);
// Compute hash for Dn
computeHashDn();
}
public ObjectName getObjectName() {
return mbean;
}
public String getDomain() {
return domain;
}
public String getKeyPropertyList() {
return keyPropertyList;
}
public Token getToken(int index) {
return tokens.get(index);
}
public int getTokenCount() {
return tokens.size();
}
public String getHashDn() {
return hashDn;
}
public String getHashKey(Token token) {
final int begin = hashDn.indexOf(token.getTokenValue());
return hashDn.substring(begin, hashDn.length());
}
private void computeHashDn() {
if (tokens.isEmpty()) {
return;
}
final StringBuilder hdn = new StringBuilder();
for (int i = 0; i < tokens.size(); i++) {
hdn.append(tokens.get(i).getTokenValue());
hdn.append(",");
}
hashDn = hdn.substring(0, hdn.length() - 1);
}
@Override
public String toString() {
return domain + ":" + keyPropertyList;
}
public int compareTo(Dn dn) {
return this.toString().compareTo(dn.toString());
}
}
private static class Token {
private String tokenType;
private String tokenValue;
private String key;
private String value;
public Token(String tokenType, String tokenValue) {
this.tokenType = tokenType;
this.tokenValue = tokenValue;
buildKeyValue();
}
public String getTokenType() {
return tokenType;
}
public String getTokenValue() {
return tokenValue;
}
public String getKey() {
return key;
}
public String getValue() {
return value;
}
private void buildKeyValue() {
int index = tokenValue.indexOf("=");
if (index < 0) {
key = tokenValue;
value = tokenValue;
} else {
key = tokenValue.substring(0, index);
value = tokenValue.substring(index + 1, tokenValue.length());
}
}
}
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.jconsole.inspector;
import java.awt.Component;
import javax.swing.ImageIcon;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
@SuppressWarnings("serial")
public class XTreeRenderer extends DefaultTreeCellRenderer {
public Component getTreeCellRendererComponent(
JTree tree, Object value, boolean selected, boolean expanded,
boolean leaf, int row, boolean hasFocus) {
super.getTreeCellRendererComponent(
tree, value, selected, expanded, leaf, row, hasFocus);
Object userObject = ((DefaultMutableTreeNode) value).getUserObject();
if (userObject instanceof XNodeInfo) {
XNodeInfo node = (XNodeInfo) userObject;
setToolTipText(node.getToolTipText());
switch (node.getType()) {
case MBEAN:
XMBean xmbean = (XMBean) node.getData();
setIcon((ImageIcon) xmbean.getIcon());
break;
case NONMBEAN:
break;
case ATTRIBUTES:
case OPERATIONS:
case NOTIFICATIONS:
setIcon(null);
break;
case ATTRIBUTE:
case OPERATION:
case NOTIFICATION:
setIcon(null);
break;
}
} else {
setToolTipText(null);
}
return this;
}
}