1 /*
   2  * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 import java.awt.Image;
  25 import java.beans.BeanDescriptor;
  26 import java.beans.BeanInfo;
  27 import java.beans.EventSetDescriptor;
  28 import java.beans.FeatureDescriptor;
  29 import java.beans.IndexedPropertyDescriptor;
  30 import java.beans.Introspector;
  31 import java.beans.MethodDescriptor;
  32 import java.beans.ParameterDescriptor;
  33 import java.beans.PropertyDescriptor;
  34 import java.lang.reflect.Array;
  35 import java.lang.reflect.Method;
  36 import java.util.Arrays;
  37 import java.util.Comparator;
  38 import java.util.Enumeration;
  39 import java.util.Map.Entry;
  40 import java.util.Objects;
  41 import java.util.TreeMap;
  42 import java.util.TreeSet;
  43 import java.util.jar.JarEntry;
  44 import java.util.jar.JarFile;
  45 import java.util.regex.Matcher;
  46 import java.util.regex.Pattern;
  47 
  48 /*
  49  * @test
  50  * @bug 4058433
  51  * @summary Generates BeanInfo for public classes in AWT, Accessibility, and Swing
  52  * @author Sergey Malenkov
  53  * @modules java.base/sun.reflect.generics.reflectiveObjects
  54  *          java.desktop/com.sun.beans
  55  *          java.desktop/com.sun.beans.util
  56  * @run main/manual Test4058433
  57  */
  58 
  59 public class Test4058433 implements Comparator<Object> {
  60     @Override
  61     public int compare(Object one, Object two) {
  62         if (one instanceof Method && two instanceof Method) {
  63             Method oneMethod = (Method) one;
  64             Method twoMethod = (Method) two;
  65             int result = oneMethod.getName().compareTo(twoMethod.getName());
  66             if (result != 0) {
  67                 return result;
  68             }
  69         }
  70         if (one instanceof FeatureDescriptor && two instanceof FeatureDescriptor) {
  71             FeatureDescriptor oneFD = (FeatureDescriptor) one;
  72             FeatureDescriptor twoFD = (FeatureDescriptor) two;
  73             int result = oneFD.getName().compareTo(twoFD.getName());
  74             if (result != 0) {
  75                 return result;
  76             }
  77         }
  78         return one.toString().compareTo(two.toString());
  79     }
  80 
  81     public static void main(String[] args) throws Exception {
  82         String resource = ClassLoader.getSystemResource("java/lang/Object.class").toString();
  83 
  84         Pattern pattern = Pattern.compile("jar:file:(.*)!.*");
  85         Matcher matcher = pattern.matcher(resource);
  86         matcher.matches();
  87         resource = matcher.group(1);
  88 
  89         TreeSet<Class<?>> types = new TreeSet<>(new Test4058433());
  90         try (JarFile jarFile = new JarFile(resource.replaceAll("%20", " "))) {
  91             Enumeration<JarEntry> entries = jarFile.entries();
  92             while (entries.hasMoreElements()) {
  93                 String name = entries.nextElement().getName();
  94                 if (name.startsWith("java/awt/") || name.startsWith("javax/accessibility/") || name.startsWith("javax/swing/")) {
  95                     if (name.endsWith(".class")) {
  96                         name = name.substring(0, name.indexOf(".")).replace('/', '.');
  97                         Class<?> type = Class.forName(name);
  98                         if (!type.isInterface() && !type.isEnum() && !type.isAnnotation() && !type.isAnonymousClass()) {
  99                             if (null == type.getDeclaringClass()) {
 100                                 types.add(type);
 101                             }
 102                         }
 103                     }
 104                 }
 105             }
 106         }
 107         System.out.println("found " + types.size() + " classes");
 108         long time = -System.currentTimeMillis();
 109         for (Class<?> type : types) {
 110             System.out.println("========================================");
 111             BeanInfo info = Introspector.getBeanInfo(type);
 112 
 113             BeanDescriptor bd = info.getBeanDescriptor();
 114             System.out.println(bd.getBeanClass());
 115             print("customizer", bd.getCustomizerClass());
 116             print(bd);
 117             print("mono 16x16", info.getIcon(BeanInfo.ICON_MONO_16x16));
 118             print("mono 32x32", info.getIcon(BeanInfo.ICON_MONO_32x32));
 119             print("color 16x16", info.getIcon(BeanInfo.ICON_COLOR_16x16));
 120             print("color 32x32", info.getIcon(BeanInfo.ICON_COLOR_32x32));
 121 
 122             PropertyDescriptor[] pds = info.getPropertyDescriptors();
 123             PropertyDescriptor dpd = getDefault(pds, info.getDefaultPropertyIndex());
 124             System.out.println(pds.length + " property descriptors");
 125             Arrays.sort(pds, new Test4058433());
 126             for (PropertyDescriptor pd : pds) {
 127                 print(pd);
 128                 if (dpd == pd) {
 129                     System.out.println("default property");
 130                 }
 131                 print("bound", pd.isBound());
 132                 print("constrained", pd.isConstrained());
 133                 print("property editor", pd.getPropertyEditorClass());
 134                 print("property type", pd.getPropertyType());
 135                 print("read method", pd.getReadMethod());
 136                 print("write method", pd.getWriteMethod());
 137                 if (pd instanceof IndexedPropertyDescriptor) {
 138                     IndexedPropertyDescriptor ipd = (IndexedPropertyDescriptor) pd;
 139                     print("indexed property type", ipd.getIndexedPropertyType());
 140                     print("indexed read method", ipd.getIndexedReadMethod());
 141                     print("indexed write method", ipd.getIndexedWriteMethod());
 142                 }
 143             }
 144             EventSetDescriptor[] esds = info.getEventSetDescriptors();
 145             EventSetDescriptor desd = getDefault(esds, info.getDefaultEventIndex());
 146             System.out.println(esds.length + " event set descriptors");
 147             Arrays.sort(esds, new Test4058433());
 148             for (EventSetDescriptor esd : esds) {
 149                 print(esd);
 150                 if (desd == esd) {
 151                     System.out.println("default event set");
 152                 }
 153                 print("in default", esd.isInDefaultEventSet());
 154                 print("unicast", esd.isUnicast());
 155                 print("listener type", esd.getListenerType());
 156                 print("get listener method", esd.getGetListenerMethod());
 157                 print("add listener method", esd.getAddListenerMethod());
 158                 print("remove listener method", esd.getRemoveListenerMethod());
 159                 Method[] methods = esd.getListenerMethods();
 160                 Arrays.sort(methods, new Test4058433());
 161                 for (Method method : methods) {
 162                     print("listener method", method);
 163                 }
 164                 print(esd.getListenerMethodDescriptors());
 165             }
 166             print(info.getMethodDescriptors());
 167         }
 168         time += System.currentTimeMillis();
 169         System.out.println("DONE IN " + time + " MS");
 170     }
 171 
 172     private static <T> T getDefault(T[] array, int index) {
 173         return (index == -1) ? null : array[index];
 174     }
 175 
 176     private static void print(MethodDescriptor[] mds) {
 177         System.out.println(mds.length + " method descriptors");
 178         Arrays.sort(mds, new Test4058433());
 179         for (MethodDescriptor md : mds) {
 180             print(md);
 181             print("method", md.getMethod());
 182             ParameterDescriptor[] pds = md.getParameterDescriptors();
 183             if (pds != null) {
 184                 System.out.println(pds.length + " parameter descriptors");
 185                 for (ParameterDescriptor pd : pds) {
 186                     print(pd);
 187                 }
 188             }
 189         }
 190     }
 191 
 192     private static void print(FeatureDescriptor descriptor) {
 193         String name = descriptor.getName();
 194         String display = descriptor.getDisplayName();
 195         String description = descriptor.getShortDescription();
 196         System.out.println("name: " + name);
 197         if (!Objects.equals(name, display)) {
 198             System.out.println("display name: " + display);
 199         }
 200         if (!Objects.equals(display, description)) {
 201             System.out.println("description: " + description.trim());
 202         }
 203         print("expert", descriptor.isExpert());
 204         print("hidden", descriptor.isHidden());
 205         print("preferred", descriptor.isPreferred());
 206         TreeMap<String,Object> map = new TreeMap<>();
 207         Enumeration<String> enumeration = descriptor.attributeNames();
 208         while (enumeration.hasMoreElements()) {
 209             String id = enumeration.nextElement();
 210             Object value = descriptor.getValue(id);
 211             if (value.getClass().isArray()) {
 212                 TreeSet<String> set = new TreeSet<>();
 213                 int index = 0;
 214                 int length = Array.getLength(value);
 215                 while (index < length) {
 216                     set.add(Array.get(value, index++) + ", " +
 217                             Array.get(value, index++) + ", " +
 218                             Array.get(value, index++));
 219                 }
 220                 value = set.toString();
 221             }
 222             map.put(id, value);
 223         }
 224         for (Entry<String,Object> entry : map.entrySet()) {
 225             System.out.println(entry.getKey() + ": " + entry.getValue());
 226         }
 227     }
 228 
 229     private static void print(String id, boolean flag) {
 230         if (flag) {
 231             System.out.println(id + " is set");
 232         }
 233     }
 234 
 235     private static void print(String id, Class<?> type) {
 236         if (type != null) {
 237             System.out.println(id + ": " + type.getName());
 238         }
 239     }
 240 
 241     private static void print(String id, Method method) {
 242         if (method != null) {
 243             System.out.println(id + ": " + method);
 244         }
 245     }
 246 
 247     private static void print(String name, Image image) {
 248         if (image != null) {
 249             System.out.println(name + " icon is exist");
 250         }
 251     }
 252 }