| /******************************************************************************* |
| * Copyright (c) 2001, 2005 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jem.beaninfo.vm; |
| |
| /* |
| * $RCSfile: BaseBeanInfo.java,v $ |
| * $Revision: 1.11 $ $Date: 2005/10/18 15:32:19 $ |
| */ |
| |
| import java.awt.Image; |
| import java.beans.*; |
| import java.lang.reflect.*; |
| |
| import org.eclipse.jem.beaninfo.common.IBaseBeanInfoConstants; |
| |
| |
| /** |
| * A BaseBeanInfo that provides common support for BeanInfos within the JEM environment. |
| * |
| * @since 1.1.0 |
| */ |
| public abstract class BaseBeanInfo extends SimpleBeanInfo implements IBaseBeanInfoConstants { |
| |
| // Constants to use to create all descriptors etc. |
| protected static java.util.ResourceBundle RESBUNDLE = java.util.ResourceBundle.getBundle("org.eclipse.jem.beaninfo.vm.beaninfo"); //$NON-NLS-1$ |
| |
| /** |
| * Bound indicator for apply property arguments. |
| * |
| * @since 1.1.0 |
| */ |
| public static final String BOUND = "bound";//$NON-NLS-1$ |
| |
| /** |
| * Constrained indicator for apply property arguments. |
| * |
| * @since 1.1.0 |
| */ |
| public static final String CONSTRAINED = "constrained";//$NON-NLS-1$ |
| |
| /** |
| * Property editor class indicator for apply property arguments. |
| * |
| * @since 1.1.0 |
| */ |
| public static final String PROPERTYEDITORCLASS = "propertyEditorClass";//$NON-NLS-1$ |
| |
| /** |
| * Read Method indicator for apply property arguments. |
| * |
| * @since 1.1.0 |
| */ |
| public static final String READMETHOD = "readMethod";//$NON-NLS-1$ |
| |
| /** |
| * Write method indicator for apply property arguments. |
| * |
| * @since 1.1.0 |
| */ |
| public static final String WRITEMETHOD = "writeMethod";//$NON-NLS-1$ |
| |
| /** |
| * Displayname indicator for apply property arguments. |
| * |
| * @since 1.1.0 |
| */ |
| public static final String DISPLAYNAME = "displayName";//$NON-NLS-1$ |
| |
| /** |
| * Expert indicator for apply property arguments. |
| * |
| * @since 1.1.0 |
| */ |
| public static final String EXPERT = "expert";//$NON-NLS-1$ |
| |
| /** |
| * Hidden indicator for apply property arguments. |
| * |
| * @since 1.1.0 |
| */ |
| public static final String HIDDEN = "hidden";//$NON-NLS-1$ |
| |
| /** |
| * Preferred indicator for apply property arguments. |
| * |
| * @since 1.1.0 |
| */ |
| public static final String PREFERRED = "preferred";//$NON-NLS-1$ |
| |
| /** |
| * Short description indicator for apply property arguments. |
| * |
| * @since 1.1.0 |
| */ |
| public static final String SHORTDESCRIPTION = "shortDescription";//$NON-NLS-1$ |
| |
| /** |
| * Customizer class indicator for apply property arguments. |
| * |
| * @since 1.1.0 |
| */ |
| public static final String CUSTOMIZERCLASS = "customizerClass";//$NON-NLS-1$ |
| |
| /** |
| * In Default eventset indicator for apply property arguments. |
| * |
| * @since 1.1.0 |
| */ |
| public static final String INDEFAULTEVENTSET = "inDefaultEventSet";//$NON-NLS-1$ |
| |
| /** |
| * This is a Feature Attribute Key. When this key exists, the value is a java.lang.reflect.Field. It means this property |
| * is a field and not a getter/setter. The getter/setter will be ignored and the property type will be the type of the field. |
| * <p> |
| * At this time, do not use field on an indexed property. This is currently an undefined situation. |
| * |
| * @since 1.1.0 |
| */ |
| public static final String FIELDPROPERTY = "field"; //$NON-NLS-1$ |
| |
| /** |
| * Obscure indicator for apply property arguments. Obsure is a pre-defined attribute name too. That is where the obscure setting is stored. |
| * <p> |
| * Obsure means most users don't need it. In the future such features won't even be cached so as to reduce the in-memory costs. Currently this |
| * flag is ignored. |
| * |
| * @since 1.1.0 |
| */ |
| public static final String OBSCURE = "ivjObscure";//$NON-NLS-1$ |
| |
| /** |
| * Design time indicator for apply property arguments. Design time is a pre-defined attribute name too. That is where the design time setting is |
| * stored. |
| * <p> |
| * Design time means: |
| * <ul> |
| * <li>Not set: Will be a property that can be connected to, and shows on property sheet (if not hidden). |
| * <li><code>true</code>: Special property (it will show on property sheet if not hidden), but it can't be connected to. Usually this is a |
| * property that is fluffed up for the IDE purposes but doesn't have a get/set method. This means it is a property for design time and not for |
| * runtime. |
| * <li><code>false</code>: This property will not show up on property sheet but it can be connected to. |
| * </ul> |
| * |
| * @since 1.1.0 |
| */ |
| public static final String DESIGNTIMEPROPERTY = "ivjDesignTimeProperty"; //$NON-NLS-1$ |
| |
| /** |
| * EventAdapterClass indicator for apply property arguments. Event adapter class is a pre-defined attribute name too. That is where the event |
| * adapter is stored. |
| * <p> |
| * Adapter class for eventSetDescriptors that provide default no-op implementation of the interface methods. For example |
| * <code>java.awt.event.WindowListener</code> has an adapter of <code>java.awt.event.WindowAdapter</code>. What is stored is actually the |
| * class name, not the class itself. |
| * |
| * @since 1.1.0 |
| */ |
| public static final String EVENTADAPTERCLASS = "eventAdapterClass"; //$NON-NLS-1$ |
| |
| |
| public static final boolean JVM_1_3 = System.getProperty("java.version", "").startsWith("1.3"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
| |
| /** |
| * Empty args list for those descriptors that don't have arguments. |
| * @since 1.1.0 |
| */ |
| public static final Object[] EMPTY_ARGS = new Object[0]; |
| |
| /** |
| * Capitalize the string. This uppercases only the first character. So if you have property name of "abc" it will become "Abc". |
| * |
| * @param s |
| * @return string with first letter capitalized. |
| * |
| * @since 1.1.0 |
| */ |
| public static String capitalize(String s) { |
| if (s.length() == 0) { return s; } |
| char chars[] = s.toCharArray(); |
| chars[0] = Character.toUpperCase(chars[0]); |
| return new String(chars); |
| } |
| |
| /** |
| * Create a BeanDescriptor object given an array of keyword/value arguments. Use the keywords defined in this class, e.g. BOUND, EXPERT, etc. |
| * |
| * @param cls |
| * bean for which the bean descriptor is being created. |
| * @param args |
| * arg pairs, [0] keyword, [1] value, [2] keyword, [3] value, etc. |
| * @return new bean descriptor |
| * |
| * @since 1.1.0 |
| */ |
| public static BeanDescriptor createBeanDescriptor(Class cls, Object[] args) { |
| Class customizerClass = null; |
| |
| /* Find the specified customizerClass */ |
| for (int i = 0; i < args.length; i += 2) { |
| if (CUSTOMIZERCLASS.equals(args[i])) { |
| customizerClass = (Class) args[i + 1]; |
| break; |
| } |
| } |
| |
| BeanDescriptor bd = new BeanDescriptor(cls, customizerClass); |
| |
| for (int i = 0; i < args.length; i += 2) { |
| String key = (String) args[i]; |
| Object value = args[i + 1]; |
| setFeatureDescriptorValue(bd, key, value); |
| } |
| |
| return bd; |
| } |
| |
| /** |
| * Create a beans EventSetDescriptor given the following: |
| * |
| * @param cls |
| * The bean class |
| * @param name |
| * Name of event set |
| * @param args |
| * arg pairs, [0] keyword, [1] value, [2] keyword, [3] value, etc. |
| * @param lmds |
| * array of MethodDescriptors defining the listener methods |
| * @param listenerType |
| * type of listener |
| * @param addListenerName |
| * add listener method name |
| * @param removeListenerNameremove |
| * listener method name |
| * @return new event set descriptor |
| * @since 1.1.0 |
| */ |
| public static EventSetDescriptor createEventSetDescriptor(Class cls, String name, Object[] args, MethodDescriptor[] lmds, Class listenerType, |
| String addListenerName, String removeListenerName) { |
| EventSetDescriptor esd = null; |
| Class[] paramTypes = { listenerType}; |
| try { |
| java.lang.reflect.Method addMethod = null; |
| java.lang.reflect.Method removeMethod = null; |
| try { |
| /* get addListenerMethod with parameter types. */ |
| addMethod = cls.getMethod(addListenerName, paramTypes); |
| } catch (Exception ie) { |
| throwError(ie, java.text.MessageFormat.format(RESBUNDLE.getString("Cannot_get_the_meth1_EXC_"), //$NON-NLS-1$ |
| new Object[] { addListenerName})); |
| } |
| ; |
| try { |
| /* get removeListenerMethod with parameter types. */ |
| removeMethod = cls.getMethod(removeListenerName, paramTypes); |
| } catch (Exception ie) { |
| throwError(ie, java.text.MessageFormat.format(RESBUNDLE.getString("Cannot_get_the_meth1_EXC_"), //$NON-NLS-1$ |
| new Object[] { removeListenerName})); |
| } |
| ; |
| |
| esd = new EventSetDescriptor(name, listenerType, lmds, addMethod, removeMethod); |
| } catch (Exception ie) { |
| throwError(ie, java.text.MessageFormat.format(RESBUNDLE.getString("Cannot_create_the_E1_EXC_"), //$NON-NLS-1$ |
| new Object[] { name})); |
| } |
| ; |
| // set the event set descriptor properties |
| for (int i = 0; i < args.length; i += 2) { |
| String key = (String) args[i]; |
| Object value = args[i + 1]; |
| if (INDEFAULTEVENTSET.equals(key)) { |
| esd.setInDefaultEventSet(((Boolean) value).booleanValue()); |
| } else |
| setFeatureDescriptorValue(esd, key, value); |
| } |
| |
| return esd; |
| } |
| |
| /** |
| * Create a bean's MethodDescriptor. |
| * |
| * @param cls |
| * class of the method. |
| * @param name |
| * name of the method. |
| * @param args |
| * arg pairs, [0] keyword, [1] value, [2] keyword, [3] value, etc. |
| * @param params |
| * parameter descriptors or <code>null</code> if no parameter descriptors. |
| * @param paramTypes |
| * parameter types |
| * @return new method descriptor |
| * |
| * @since 1.1.0 |
| */ |
| public static MethodDescriptor createMethodDescriptor(Class cls, String name, Object[] args, ParameterDescriptor[] params, Class[] paramTypes) { |
| MethodDescriptor md = null; |
| try { |
| java.lang.reflect.Method aMethod = null; |
| try { |
| /* getMethod with parameter types. */ |
| aMethod = cls.getMethod(name, paramTypes); |
| } catch (Exception ie) { |
| throwError(ie, java.text.MessageFormat.format(RESBUNDLE.getString("Cannot_get_the_meth1_EXC_"), //$NON-NLS-1$ |
| new Object[] { name})); |
| } |
| ; |
| if (params != null && params.length > 0) |
| md = new MethodDescriptor(aMethod, params); |
| else |
| md = new MethodDescriptor(aMethod); |
| } catch (Exception ie) { |
| throwError(ie, java.text.MessageFormat.format(RESBUNDLE.getString("Cannot_create_Method_EXC_"), //$NON-NLS-1$ |
| new Object[] { name})); |
| } |
| ; |
| // set the method properties |
| for (int i = 0; i < args.length; i += 2) { |
| String key = (String) args[i]; |
| Object value = args[i + 1]; |
| setFeatureDescriptorValue(md, key, value); |
| } |
| return md; |
| } |
| |
| private static PropertyDescriptor createOtherPropertyDescriptor(String name, Class cls) throws IntrospectionException { |
| Method readMethod = null; |
| Method writeMethod = null; |
| String base = capitalize(name); |
| Class[] parameters = new Class[0]; |
| |
| // First we try boolean accessor pattern |
| try { |
| readMethod = cls.getMethod("is" + base, parameters);//$NON-NLS-1$ |
| } catch (Exception ex1) { |
| } |
| if (readMethod == null) { |
| try { |
| // Else we try the get accessor pattern. |
| readMethod = cls.getMethod("get" + base, parameters);//$NON-NLS-1$ |
| } catch (Exception ex2) { |
| // Find by matching methods of the class |
| readMethod = findMethod(cls, "get" + base, 0);//$NON-NLS-1$ |
| } |
| } |
| |
| if (readMethod == null) { |
| // For write-only properties, find the write method |
| writeMethod = findMethod(cls, "set" + base, 1);//$NON-NLS-1$ |
| } else { |
| // In Sun's code, reflection fails if there are two |
| // setters with the same name and the first setter located |
| // does not have the same return type of the getter. |
| // This fixes that. |
| parameters = new Class[1]; |
| parameters[0] = readMethod.getReturnType(); |
| try { |
| writeMethod = cls.getMethod("set" + base, parameters);//$NON-NLS-1$ |
| } catch (Exception ex3) { |
| } |
| } |
| // create the property descriptor |
| if ((readMethod != null) || (writeMethod != null)) { |
| return new PropertyDescriptor(name, readMethod, writeMethod); |
| } else { |
| throw new IntrospectionException(java.text.MessageFormat.format(RESBUNDLE.getString("Cannot_find_the_acc1_EXC_"), //$NON-NLS-1$ |
| new Object[] { name})); |
| } |
| } |
| |
| /** |
| * Create a beans parameter descriptor. |
| * |
| * @param name |
| * name of parameter |
| * @param args |
| * arg pairs, [0] keyword, [1] value, [2] keyword, [3] value, etc. |
| * @return new parameter descriptor |
| * |
| * @since 1.1.0 |
| */ |
| public static ParameterDescriptor createParameterDescriptor(String name, Object[] args) { |
| ParameterDescriptor pd = null; |
| try { |
| pd = new ParameterDescriptor(); |
| } catch (Exception ie) { |
| throwError(ie, java.text.MessageFormat.format(RESBUNDLE.getString("Cannot_create_Param1_EXC_"), //$NON-NLS-1$ |
| new Object[] { name})); |
| } |
| ; |
| // set the name |
| pd.setName(name); |
| // set the method properties |
| for (int i = 0; i < args.length; i += 2) { |
| String key = (String) args[i]; |
| Object value = args[i + 1]; |
| setFeatureDescriptorValue(pd, key, value); |
| } |
| |
| return pd; |
| } |
| |
| private static Method GETCLASS; |
| |
| static { |
| try { |
| GETCLASS = Object.class.getMethod("getClass", null); //$NON-NLS-1$ |
| } catch (SecurityException e) { |
| } catch (NoSuchMethodException e) { |
| } |
| } |
| /** |
| * Create a property descriptor describing a field property. |
| * <p> |
| * Note: This is non-standard. The VE knows how to handle this, but any one else using BeanInfo will see this as a property with |
| * no getter or setter. |
| * @param name |
| * @param field |
| * @param args |
| * @return |
| * |
| * @since 1.1.0 |
| */ |
| public static PropertyDescriptor createFieldPropertyDescriptor(String name, Field field, Object[] args) { |
| try { |
| PropertyDescriptor pd = new PropertyDescriptor(name, null, null); |
| pd.setValue(FIELDPROPERTY, field); // Set the field property so we know it is a field. |
| applyFieldArguments(pd, args); |
| // Need to set in a phony read method because Introspector will throw it away otherwise. We just use Object.getClass for this. |
| // We will ignore the property type for fields. If used outside of VE then it will look like a class property. |
| pd.setReadMethod(GETCLASS); |
| return pd; |
| } catch (IntrospectionException e) { |
| throwError(e, java.text.MessageFormat.format(RESBUNDLE.getString("Cannot_create_the_P1_EXC_"), //$NON-NLS-1$ |
| new Object[] { name})); |
| return null; |
| } |
| } |
| |
| /** |
| * Create a bean's property descriptor. |
| * |
| * @param cls |
| * class of who owns the property (usually the bean). It is used to look up get/set methods for the property. |
| * @param name |
| * name of the property. It will use get{Name} and set{Name} to find get/set methods. |
| * @param args |
| * arg pairs, [0] keyword, [1] value, [2] keyword, [3] value, etc. |
| * @return new property descriptor |
| * |
| * @since 1.1.0 |
| */ |
| public static PropertyDescriptor createPropertyDescriptor(Class cls, String name, Object[] args) { |
| PropertyDescriptor pd = null; |
| try { |
| // Create assuming that the getter/setter follows reflection patterns |
| pd = new PropertyDescriptor(name, cls); |
| } catch (IntrospectionException e) { |
| // Try creating a property descriptor for read-only, write-only |
| // or if Sun's reflection fails |
| try { |
| pd = createOtherPropertyDescriptor(name, cls); |
| } catch (IntrospectionException ie) { |
| throwError(ie, java.text.MessageFormat.format(RESBUNDLE.getString("Cannot_create_the_P1_EXC_"), //$NON-NLS-1$ |
| new Object[] { name})); |
| } |
| } |
| |
| applyPropertyArguments(pd, args, cls); |
| |
| return pd; |
| } |
| |
| |
| /** |
| * Create a new PropertyDescriptor based upon the PD sent in. It will clone the sent in one, and apply the args to override any specific setting. |
| * Class cls is used for finding read/write methods, if any. |
| * |
| * This is used when wanting to override only a few specific settings from a property descriptor from the super class. |
| * |
| * @param fromPDS |
| * The PropertyDescriptor array to find the entry to clone. It will be changed in place in the array. |
| * @param name |
| * The name of the property to find and clone and override. |
| * @param cls |
| * The class to use to find read/write methods in args. If no read/write methods specified, then this may be null. |
| * @param args |
| * The arguments to override from fromPD. arg pairs, [0] keyword, [1] value, [2] keyword, [3] value, etc. |
| */ |
| public void replacePropertyDescriptor(PropertyDescriptor[] pds, String name, Class cls, Object[] args) { |
| PropertyDescriptor pd = null; |
| int iPD = findPropertyDescriptor(pds, name); |
| if (iPD == -1) |
| return; |
| PropertyDescriptor fromPD = pds[iPD]; |
| try { |
| |
| pd = pds[iPD] = new PropertyDescriptor(fromPD.getName(), null, null); |
| } catch (IntrospectionException e) { |
| throwError(e, java.text.MessageFormat.format(RESBUNDLE.getString("Cannot_create_the_P1_EXC_"), //$NON-NLS-1$ |
| new Object[] { fromPD.getName()})); |
| } |
| |
| // Now copy over the contents of fromPD. |
| clonePropertySettings(fromPD, pd); |
| |
| // Now apply the overrides |
| applyPropertyArguments(pd, args, cls); |
| return; |
| } |
| |
| private void clonePropertySettings(PropertyDescriptor fromPD, PropertyDescriptor pd) { |
| try { |
| pd.setReadMethod(fromPD.getReadMethod()); |
| pd.setWriteMethod(fromPD.getWriteMethod()); |
| pd.setPropertyEditorClass(fromPD.getPropertyEditorClass()); |
| pd.setBound(fromPD.isBound()); |
| pd.setConstrained(fromPD.isConstrained()); |
| cloneFeatureSettings(fromPD, pd); |
| } catch (IntrospectionException e) { |
| throwError(e, java.text.MessageFormat.format(RESBUNDLE.getString("Cannot_create_the_P1_EXC_"), //$NON-NLS-1$ |
| new Object[] { fromPD.getName()})); |
| } |
| } |
| |
| private void cloneFeatureSettings(FeatureDescriptor fromFD, FeatureDescriptor fd) { |
| fd.setExpert(fromFD.isExpert()); |
| fd.setHidden(fromFD.isHidden()); |
| fd.setPreferred(fromFD.isPreferred()); |
| fd.setShortDescription(fromFD.getShortDescription()); |
| fd.setDisplayName(fromFD.getDisplayName()); |
| |
| java.util.Enumeration keys = fromFD.attributeNames(); |
| while (keys.hasMoreElements()) { |
| String key = (String) keys.nextElement(); |
| Object value = fromFD.getValue(key); |
| fd.setValue(key, value); |
| } |
| } |
| |
| /* |
| * The common property arguments between field and standard properties. |
| */ |
| private static boolean applyCommonPropertyArguments(PropertyDescriptor pd, String key, Object value) { |
| if (BOUND.equals(key)) { |
| pd.setBound(((Boolean) value).booleanValue()); |
| } else if (CONSTRAINED.equals(key)) { |
| pd.setConstrained(((Boolean) value).booleanValue()); |
| } else if (PROPERTYEDITORCLASS.equals(key)) { |
| pd.setPropertyEditorClass((Class) value); |
| } else if (FIELDPROPERTY.equals(key)) |
| return true; // This should not be applied except through createFieldProperty. |
| else |
| return false; |
| return true; |
| |
| } |
| |
| private static void applyPropertyArguments(PropertyDescriptor pd, Object[] args, Class cls) { |
| for (int i = 0; i < args.length; i += 2) { |
| String key = (String) args[i]; |
| Object value = args[i + 1]; |
| |
| if (!applyCommonPropertyArguments(pd, key, value)) { |
| if (READMETHOD.equals(key)) { |
| String methodName = (String) value; |
| Method method; |
| try { |
| method = cls.getMethod(methodName, new Class[0]); |
| pd.setReadMethod(method); |
| } catch (Exception e) { |
| throwError(e, java.text.MessageFormat.format(RESBUNDLE.getString("{0}_no_read_method_EXC_"), //$NON-NLS-1$ |
| new Object[] { cls, methodName})); |
| } |
| } else if (WRITEMETHOD.equals(key)) { |
| String methodName = (String) value; |
| try { |
| if (methodName == null) { |
| pd.setWriteMethod(null); |
| } else { |
| Method method; |
| Class type = pd.getPropertyType(); |
| method = cls.getMethod(methodName, new Class[] { type}); |
| pd.setWriteMethod(method); |
| } |
| } catch (Exception e) { |
| throwError(e, java.text.MessageFormat.format(RESBUNDLE.getString("{0}_no_write_method_EXC_"), //$NON-NLS-1$ |
| new Object[] { cls, methodName})); |
| } |
| } else { |
| // arbitrary value |
| setFeatureDescriptorValue(pd, key, value); |
| } |
| } |
| } |
| } |
| |
| private static void applyFieldArguments(PropertyDescriptor pd, Object[] args) { |
| for (int i = 0; i < args.length; i += 2) { |
| String key = (String) args[i]; |
| Object value = args[i + 1]; |
| |
| if (!applyCommonPropertyArguments(pd, key, value)) { |
| if (READMETHOD.equals(key)) { |
| // ignored for field. |
| } else if (WRITEMETHOD.equals(key)) { |
| // ignored for field. |
| } else { |
| // arbitrary value |
| setFeatureDescriptorValue(pd, key, value); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Find the method by comparing (name & parameter size) against the methods in the class. This is an expensive call and should be used only if |
| * getMethod with specific parameter types can't find method. |
| * |
| * @return java.lang.reflect.Method |
| * @param aClass |
| * java.lang.Class |
| * @param methodName |
| * java.lang.String |
| * @param parameterCount |
| * int |
| */ |
| public static java.lang.reflect.Method findMethod(java.lang.Class aClass, java.lang.String methodName, int parameterCount) { |
| try { |
| /* |
| * Since this method attempts to find a method by getting all methods from the class, this method should only be called if getMethod |
| * cannot find the method. |
| */ |
| java.lang.reflect.Method methods[] = aClass.getMethods(); |
| for (int index = 0; index < methods.length; index++) { |
| java.lang.reflect.Method method = methods[index]; |
| if ((method.getParameterTypes().length == parameterCount) && (method.getName().equals(methodName))) { return method; } |
| ; |
| } |
| ; |
| } catch (java.lang.Throwable exception) { |
| return null; |
| } |
| ; |
| return null; |
| } |
| |
| /** |
| * Find a property descriptor of a given name in the list. |
| * |
| * @param pds |
| * The array of property descriptors to search, may be null. |
| * @param name |
| * The name to search for. |
| * @return The found property descriptor index, or -1 if not found. |
| */ |
| public static int findPropertyDescriptor(PropertyDescriptor[] pds, String name) { |
| for (int i = 0; i < pds.length; i++) { |
| if (name.equals(pds[i].getName())) |
| return i; |
| } |
| return -1; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see java.beans.BeanInfo#getDefaultEventIndex() |
| */ |
| public int getDefaultEventIndex() { |
| return -1; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see java.beans.BeanInfo#getDefaultPropertyIndex() |
| */ |
| public int getDefaultPropertyIndex() { |
| return -1; |
| } |
| |
| |
| /* (non-Javadoc) |
| * @see java.beans.SimpleBeanInfo#getBeanDescriptor() |
| */ |
| public BeanDescriptor getBeanDescriptor() { |
| // Default is to create an empty one. |
| return createBeanDescriptor(getBeanClass(), EMPTY_ARGS); |
| } |
| |
| /** |
| * Implementation for BeanInfo. This implementation will return the BeanInfo of the superclass. |
| * |
| * @see BeanInfo#getAdditionalBeanInfo() |
| * @since 1.1.0 |
| */ |
| public BeanInfo[] getAdditionalBeanInfo() { |
| try { |
| BeanInfo[] result = new BeanInfo[] { Introspector.getBeanInfo(getBeanClass().getSuperclass())}; |
| PropertyDescriptor[] oPDs = result[0].getPropertyDescriptors(); |
| PropertyDescriptor[] nPDs = overridePropertyDescriptors(oPDs); |
| if (oPDs != nPDs) |
| result[0] = new OverridePDBeanInfo(result[0], nPDs); |
| return result; |
| } catch (IntrospectionException e) { |
| return new BeanInfo[0]; |
| } |
| } |
| |
| private static class OverridePDBeanInfo implements BeanInfo { |
| |
| private BeanInfo originalBeanInfo; |
| |
| private PropertyDescriptor[] overridePDs; |
| |
| public OverridePDBeanInfo(BeanInfo bi, PropertyDescriptor[] pds) { |
| originalBeanInfo = bi; |
| overridePDs = pds; |
| } |
| |
| public BeanInfo[] getAdditionalBeanInfo() { |
| return originalBeanInfo.getAdditionalBeanInfo(); |
| } |
| |
| public BeanDescriptor getBeanDescriptor() { |
| return originalBeanInfo.getBeanDescriptor(); |
| } |
| |
| public int getDefaultEventIndex() { |
| return originalBeanInfo.getDefaultEventIndex(); |
| } |
| |
| public int getDefaultPropertyIndex() { |
| return originalBeanInfo.getDefaultPropertyIndex(); |
| } |
| |
| public EventSetDescriptor[] getEventSetDescriptors() { |
| return originalBeanInfo.getEventSetDescriptors(); |
| } |
| |
| public Image getIcon(int iconKind) { |
| return originalBeanInfo.getIcon(iconKind); |
| } |
| |
| public MethodDescriptor[] getMethodDescriptors() { |
| return originalBeanInfo.getMethodDescriptors(); |
| } |
| |
| public PropertyDescriptor[] getPropertyDescriptors() { |
| return overridePDs; |
| } |
| } |
| |
| /** |
| * Allow overrides to parent beaninfo. Subclasses should override this method if they wish to override and change any inherited properties. This |
| * allows removal of inherited properties or changes of specific properties (such as change from hidden to not hidden). |
| * |
| * Note: If there any changes, this must return a DIFFERENT array. If it returns the same array, then the changes will not be accepted. If just |
| * overriding, should use pds.clone() to get the new array and then change the specific entries. |
| * |
| * @param pds |
| * @return The new changed array or the same array if no changes. |
| * @since 1.1.0 |
| */ |
| protected PropertyDescriptor[] overridePropertyDescriptors(PropertyDescriptor[] pds) { |
| return pds; |
| } |
| |
| /** |
| * Get the bean class this beaninfo is for. Used by subclasses to quickly get the bean class without having to code it over and over. |
| * |
| * @return bean class for this beaninfo. |
| * |
| * @since 1.1.0 |
| */ |
| public abstract Class getBeanClass(); |
| |
| /** |
| * Called whenever the bean information class throws an exception. By default it prints a message and then a stacktrace to sys err. |
| * |
| * @param exception |
| * java.lang.Throwable |
| * @since 1.1.0 |
| */ |
| public void handleException(Throwable exception) { |
| System.err.println(RESBUNDLE.getString("UNCAUGHT_EXC_")); //$NON-NLS-1$ |
| exception.printStackTrace(); |
| } |
| |
| private static void setFeatureDescriptorValue(FeatureDescriptor fd, String key, Object value) { |
| if (DISPLAYNAME.equals(key)) { |
| fd.setDisplayName((String) value); |
| } else if (EXPERT.equals(key)) { |
| fd.setExpert(((Boolean) value).booleanValue()); |
| } else if (HIDDEN.equals(key)) { |
| fd.setHidden(((Boolean) value).booleanValue()); |
| } else if (PREFERRED.equals(key)) { |
| fd.setPreferred(((Boolean) value).booleanValue()); |
| if (JVM_1_3) { |
| // Bug in 1.3 doesn't preserve the preferred flag, so we will put it into the attributes too. |
| fd.setValue(PREFERRED, value); |
| } |
| } else if (SHORTDESCRIPTION.equals(key)) { |
| fd.setShortDescription((String) value); |
| } |
| // Otherwise assume an arbitrary-named value |
| // Assume that the FeatureDescriptor private hashTable\ |
| // contains only arbitrary-named attributes |
| else { |
| fd.setValue(key, value); |
| } |
| } |
| |
| /** |
| * Fatal errors are handled by calling this method. By default it throws an Error exception. |
| * |
| * @param e |
| * exception exception message placed into the new Error thrown. |
| * @param s |
| * message added to exception message. <code>null</code> if nothing to add. |
| * |
| * @throws Error |
| * turns exception into an Error. |
| * @since 1.1.0 |
| */ |
| protected static void throwError(Exception e, String s) { |
| throw new Error(e.toString() + " " + s);//$NON-NLS-1$ |
| } |
| } |