462 lines · 16.3 KB · Java
RawDownload
/* * 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.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.toString().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();        }    }}