Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/make/data/swingbeaninfo/sun/swing/BeanInfoUtils.java
38892 views
/*1* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.swing;2627import java.beans.*;28import java.lang.reflect.Method;2930public class BeanInfoUtils31{32/* The values of these createPropertyDescriptor() and33* createBeanDescriptor() keywords are the names of the34* properties they're used to set.35*/36public static final String BOUND = "bound";37public static final String CONSTRAINED = "constrained";38public static final String PROPERTYEDITORCLASS = "propertyEditorClass";39public static final String READMETHOD = "readMethod";40public static final String WRITEMETHOD = "writeMethod";41public static final String DISPLAYNAME = "displayName";42public static final String EXPERT = "expert";43public static final String HIDDEN = "hidden";44public static final String PREFERRED = "preferred";45public static final String SHORTDESCRIPTION = "shortDescription";46public static final String CUSTOMIZERCLASS = "customizerClass";4748static private void initFeatureDescriptor(FeatureDescriptor fd, String key, Object value)49{50if (DISPLAYNAME.equals(key)) {51fd.setDisplayName((String)value);52}5354if (EXPERT.equals(key)) {55fd.setExpert(((Boolean)value).booleanValue());56}5758if (HIDDEN.equals(key)) {59fd.setHidden(((Boolean)value).booleanValue());60}6162if (PREFERRED.equals(key)) {63fd.setPreferred(((Boolean)value).booleanValue());64}6566else if (SHORTDESCRIPTION.equals(key)) {67fd.setShortDescription((String)value);68}6970/* Otherwise assume that we have an arbitrary FeatureDescriptor71* "attribute".72*/73else {74fd.setValue(key, value);75}76}7778/**79* Create a beans PropertyDescriptor given an of keyword/value80* arguments. The following sample call shows all of the supported81* keywords:82*<pre>83* createPropertyDescriptor("contentPane", new Object[] {84* BOUND, Boolean.TRUE,85* CONSTRAINED, Boolean.TRUE,86* PROPERTYEDITORCLASS, package.MyEditor.class,87* READMETHOD, "getContentPane",88* WRITEMETHOD, "setContentPane",89* DISPLAYNAME, "contentPane",90* EXPERT, Boolean.FALSE,91* HIDDEN, Boolean.FALSE,92* PREFERRED, Boolean.TRUE,93* SHORTDESCRIPTION, "A top level window with a window manager border",94* "random attribute","random object value"95* }96* );97* </pre>98* The keywords correspond to <code>java.beans.PropertyDescriptor</code> and99* <code>java.beans.FeatureDescriptor</code> properties, e.g. providing a value100* for displayName is comparable to <code>FeatureDescriptor.setDisplayName()</code>.101* Using createPropertyDescriptor instead of the PropertyDescriptor102* constructor and set methods is preferrable in that it regularizes103* the code in a <code>java.beans.BeanInfo.getPropertyDescriptors()</code>104* method implementation. One can use <code>createPropertyDescriptor</code>105* to set <code>FeatureDescriptor</code> attributes, as in "random attribute"106* "random object value".107* <p>108* All properties should provide a reasonable value for the109* <code>SHORTDESCRIPTION</code> keyword and should set <code>BOUND</code>110* to <code>Boolean.TRUE</code> if neccessary. The remaining keywords111* are optional. There's no need to provide values for keywords like112* READMETHOD if the correct value can be computed, i.e. if the properties113* get/is method follows the standard beans pattern.114* <p>115* The PREFERRED keyword is not supported by the JDK1.1 java.beans package.116* It's still worth setting it to true for properties that are most117* likely to be interested to the average developer, e.g. AbstractButton.title118* is a preferred property, AbstractButton.focusPainted is not.119*120* @see java.beans#BeanInfo121* @see java.beans#PropertyDescriptor122* @see java.beans#FeatureDescriptor123*/124public static PropertyDescriptor createPropertyDescriptor(Class cls, String name, Object[] args)125{126PropertyDescriptor pd = null;127try {128pd = new PropertyDescriptor(name, cls);129} catch (IntrospectionException e) {130// Try creating a read-only property, in case setter isn't defined.131try {132pd = createReadOnlyPropertyDescriptor(name, cls);133} catch (IntrospectionException ie) {134throwError(ie, "Can't create PropertyDescriptor for " + name + " ");135}136}137138for(int i = 0; i < args.length; i += 2) {139String key = (String)args[i];140Object value = args[i + 1];141142if (BOUND.equals(key)) {143pd.setBound(((Boolean)value).booleanValue());144}145146else if (CONSTRAINED.equals(key)) {147pd.setConstrained(((Boolean)value).booleanValue());148}149150else if (PROPERTYEDITORCLASS.equals(key)) {151pd.setPropertyEditorClass((Class)value);152}153154else if (READMETHOD.equals(key)) {155String methodName = (String)value;156Method method;157try {158method = cls.getMethod(methodName, new Class[0]);159pd.setReadMethod(method);160}161catch(Exception e) {162throwError(e, cls + " no such method as \"" + methodName + "\"");163}164}165166else if (WRITEMETHOD.equals(key)) {167String methodName = (String)value;168Method method;169try {170Class type = pd.getPropertyType();171method = cls.getMethod(methodName, new Class[]{type});172pd.setWriteMethod(method);173}174catch(Exception e) {175throwError(e, cls + " no such method as \"" + methodName + "\"");176}177}178179else {180initFeatureDescriptor(pd, key, value);181}182}183184return pd;185}186187188/**189* Create a BeanDescriptor object given an of keyword/value190* arguments. The following sample call shows all of the supported191* keywords:192*<pre>193* createBeanDescriptor(JWindow..class, new Object[] {194* CUSTOMIZERCLASS, package.MyCustomizer.class,195* DISPLAYNAME, "JFrame",196* EXPERT, Boolean.FALSE,197* HIDDEN, Boolean.FALSE,198* PREFERRED, Boolean.TRUE,199* SHORTDESCRIPTION, "A top level window with a window manager border",200* "random attribute","random object value"201* }202* );203* </pre>204* The keywords correspond to <code>java.beans.BeanDescriptor</code> and205* <code>java.beans.FeatureDescriptor</code> properties, e.g. providing a value206* for displayName is comparable to <code>FeatureDescriptor.setDisplayName()</code>.207* Using createBeanDescriptor instead of the BeanDescriptor208* constructor and set methods is preferrable in that it regularizes209* the code in a <code>java.beans.BeanInfo.getBeanDescriptor()</code>210* method implementation. One can use <code>createBeanDescriptor</code>211* to set <code>FeatureDescriptor</code> attributes, as in "random attribute"212* "random object value".213*214* @see java.beans#BeanInfo215* @see java.beans#PropertyDescriptor216*/217public static BeanDescriptor createBeanDescriptor(Class cls, Object[] args)218{219Class customizerClass = null;220221/* For reasons I don't understand, customizerClass is a222* readOnly property. So we have to find it and pass it223* to the constructor here.224*/225for(int i = 0; i < args.length; i += 2) {226if (CUSTOMIZERCLASS.equals((String)args[i])) {227customizerClass = (Class)args[i + 1];228break;229}230}231232BeanDescriptor bd = new BeanDescriptor(cls, customizerClass);233234for(int i = 0; i < args.length; i += 2) {235String key = (String)args[i];236Object value = args[i + 1];237initFeatureDescriptor(bd, key, value);238}239240return bd;241}242243static private PropertyDescriptor createReadOnlyPropertyDescriptor(244String name, Class cls) throws IntrospectionException {245246Method readMethod = null;247String base = capitalize(name);248Class[] parameters = new Class[0];249250// Is it a boolean?251try {252readMethod = cls.getMethod("is" + base, parameters);253} catch (Exception ex) {}254if (readMethod == null) {255try {256// Try normal accessor pattern.257readMethod = cls.getMethod("get" + base, parameters);258} catch (Exception ex2) {}259}260if (readMethod != null) {261return new PropertyDescriptor(name, readMethod, null);262}263264try {265// Try indexed accessor pattern.266parameters = new Class[1];267parameters[0] = int.class;268readMethod = cls.getMethod("get" + base, parameters);269} catch (NoSuchMethodException nsme) {270throw new IntrospectionException(271"cannot find accessor method for " + name + " property.");272}273return new IndexedPropertyDescriptor(name, null, null, readMethod, null);274}275276// Modified methods from java.beans.Introspector277private static String capitalize(String s) {278if (s.length() == 0) {279return s;280}281char chars[] = s.toCharArray();282chars[0] = Character.toUpperCase(chars[0]);283return new String(chars);284}285286/**287* Fatal errors are handled by calling this method.288*/289public static void throwError(Exception e, String s) {290throw new Error(e.toString() + " " + s);291}292}293294295