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
24import java.awt.Image;
25import java.beans.BeanDescriptor;
26import java.beans.BeanInfo;
27import java.beans.EventSetDescriptor;
28import java.beans.FeatureDescriptor;
29import java.beans.IndexedPropertyDescriptor;
30import java.beans.Introspector;
31import java.beans.MethodDescriptor;
32import java.beans.ParameterDescriptor;
33import java.beans.PropertyDescriptor;
34import java.lang.reflect.Array;
35import java.lang.reflect.Method;
36import java.net.URI;
37import java.nio.file.FileSystem;
38import java.nio.file.FileSystems;
39import java.nio.file.FileVisitResult;
40import java.nio.file.Files;
41import java.nio.file.Path;
42import java.nio.file.SimpleFileVisitor;
43import java.nio.file.attribute.BasicFileAttributes;
44import java.util.Arrays;
45import java.util.Comparator;
46import java.util.Enumeration;
47import java.util.Map.Entry;
48import java.util.Objects;
49import java.util.TreeMap;
50import java.util.TreeSet;
51
52/*
53 * @test
54 * @bug 4058433
55 * @summary Generates BeanInfo for public classes in AWT, Accessibility, and Swing
56 * @author Sergey Malenkov
57 */
58public class Test4058433 implements Comparator<Object> {
59    @Override
60    public int compare(Object one, Object two) {
61        if (one instanceof Method && two instanceof Method) {
62            Method oneMethod = (Method) one;
63            Method twoMethod = (Method) two;
64            int result = oneMethod.getName().compareTo(twoMethod.getName());
65            if (result != 0) {
66                return result;
67            }
68        }
69        if (one instanceof FeatureDescriptor && two instanceof FeatureDescriptor) {
70            FeatureDescriptor oneFD = (FeatureDescriptor) one;
71            FeatureDescriptor twoFD = (FeatureDescriptor) two;
72            int result = oneFD.getName().compareTo(twoFD.getName());
73            if (result != 0) {
74                return result;
75            }
76        }
77        return one.toString().compareTo(two.toString());
78    }
79
80    public static void main(String[] args) throws Exception {
81        FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
82        fs.getFileStores();
83
84        TreeSet<Class<?>> types = new TreeSet<>(new Test4058433());
85        Files.walkFileTree(fs.getPath("/modules/java.desktop"), new SimpleFileVisitor<Path>() {
86            @Override
87            public FileVisitResult visitFile(Path file,
88                                             BasicFileAttributes attrs) {
89                file = file.subpath(2, file.getNameCount());
90                if (file.startsWith("java/awt/")
91                        || file.startsWith("javax/accessibility/")
92                        || file.startsWith("javax/swing/")) {
93                    String name =file.toString();
94                    if (name.endsWith(".class")) {
95                        name = name.substring(0, name.indexOf(".")).replace('/', '.');
96
97                        final Class<?> type;
98                        try {
99                            type = Class.forName(name);
100                        } catch (ClassNotFoundException e) {
101                            throw new RuntimeException(e);
102                        }
103                        if (!BeanInfo.class.isAssignableFrom(type) && !type.isInterface()
104                            && !type.isEnum() && !type.isAnnotation()
105                            && !type.isAnonymousClass()) {
106                            if (null == type.getDeclaringClass()) {
107                                types.add(type);
108                            }
109                        }
110                    }
111                }
112                return FileVisitResult.CONTINUE;
113            }
114        });
115
116        System.out.println("found " + types.size() + " classes");
117        long time = -System.currentTimeMillis();
118        for (Class<?> type : types) {
119            System.out.println("========================================");
120            BeanInfo info = Introspector.getBeanInfo(type);
121
122            BeanDescriptor bd = info.getBeanDescriptor();
123            System.out.println(bd.getBeanClass());
124            print("customizer", bd.getCustomizerClass());
125            print(bd);
126            print("mono 16x16", info.getIcon(BeanInfo.ICON_MONO_16x16));
127            print("mono 32x32", info.getIcon(BeanInfo.ICON_MONO_32x32));
128            print("color 16x16", info.getIcon(BeanInfo.ICON_COLOR_16x16));
129            print("color 32x32", info.getIcon(BeanInfo.ICON_COLOR_32x32));
130
131            PropertyDescriptor[] pds = info.getPropertyDescriptors();
132            PropertyDescriptor dpd = getDefault(pds, info.getDefaultPropertyIndex());
133            System.out.println(pds.length + " property descriptors");
134            Arrays.sort(pds, new Test4058433());
135            for (PropertyDescriptor pd : pds) {
136                print(pd);
137                if (dpd == pd) {
138                    System.out.println("default property");
139                }
140                print("bound", pd.isBound());
141                print("constrained", pd.isConstrained());
142                print("property editor", pd.getPropertyEditorClass());
143                print("property type", pd.getPropertyType());
144                print("read method", pd.getReadMethod());
145                print("write method", pd.getWriteMethod());
146                if (pd instanceof IndexedPropertyDescriptor) {
147                    IndexedPropertyDescriptor ipd = (IndexedPropertyDescriptor) pd;
148                    print("indexed property type", ipd.getIndexedPropertyType());
149                    print("indexed read method", ipd.getIndexedReadMethod());
150                    print("indexed write method", ipd.getIndexedWriteMethod());
151                }
152            }
153            EventSetDescriptor[] esds = info.getEventSetDescriptors();
154            EventSetDescriptor desd = getDefault(esds, info.getDefaultEventIndex());
155            System.out.println(esds.length + " event set descriptors");
156            Arrays.sort(esds, new Test4058433());
157            for (EventSetDescriptor esd : esds) {
158                print(esd);
159                if (desd == esd) {
160                    System.out.println("default event set");
161                }
162                print("in default", esd.isInDefaultEventSet());
163                print("unicast", esd.isUnicast());
164                print("listener type", esd.getListenerType());
165                print("get listener method", esd.getGetListenerMethod());
166                print("add listener method", esd.getAddListenerMethod());
167                print("remove listener method", esd.getRemoveListenerMethod());
168                Method[] methods = esd.getListenerMethods();
169                Arrays.sort(methods, new Test4058433());
170                for (Method method : methods) {
171                    print("listener method", method);
172                }
173                print(esd.getListenerMethodDescriptors());
174            }
175            print(info.getMethodDescriptors());
176        }
177        time += System.currentTimeMillis();
178        System.out.println("DONE IN " + time + " MS");
179    }
180
181    private static <T> T getDefault(T[] array, int index) {
182        return (index == -1) ? null : array[index];
183    }
184
185    private static void print(MethodDescriptor[] mds) {
186        System.out.println(mds.length + " method descriptors");
187        Arrays.sort(mds, new Test4058433());
188        for (MethodDescriptor md : mds) {
189            print(md);
190            print("method", md.getMethod());
191            ParameterDescriptor[] pds = md.getParameterDescriptors();
192            if (pds != null) {
193                System.out.println(pds.length + " parameter descriptors");
194                for (ParameterDescriptor pd : pds) {
195                    print(pd);
196                }
197            }
198        }
199    }
200
201    private static void print(FeatureDescriptor descriptor) {
202        String name = descriptor.getName();
203        String display = descriptor.getDisplayName();
204        String description = descriptor.getShortDescription();
205        System.out.println("name: " + name);
206        if (!Objects.equals(name, display)) {
207            System.out.println("display name: " + display);
208        }
209        if (!Objects.equals(display, description)) {
210            System.out.println("description: " + description.trim());
211        }
212        print("expert", descriptor.isExpert());
213        print("hidden", descriptor.isHidden());
214        print("preferred", descriptor.isPreferred());
215        TreeMap<String,Object> map = new TreeMap<>();
216        Enumeration<String> enumeration = descriptor.attributeNames();
217        while (enumeration.hasMoreElements()) {
218            String id = enumeration.nextElement();
219            Object value = descriptor.getValue(id);
220            if (value.getClass().isArray()) {
221                TreeSet<String> set = new TreeSet<>();
222                int index = 0;
223                int length = Array.getLength(value);
224                while (index < length) {
225                    set.add(Array.get(value, index++) + ", " +
226                            Array.get(value, index++) + ", " +
227                            Array.get(value, index++));
228                }
229                value = set.toString();
230            }
231            map.put(id, value);
232        }
233        for (Entry<String,Object> entry : map.entrySet()) {
234            System.out.println(entry.getKey() + ": " + entry.getValue());
235        }
236    }
237
238    private static void print(String id, boolean flag) {
239        if (flag) {
240            System.out.println(id + " is set");
241        }
242    }
243
244    private static void print(String id, Class<?> type) {
245        if (type != null) {
246            System.out.println(id + ": " + type.getName());
247        }
248    }
249
250    private static void print(String id, Method method) {
251        if (method != null) {
252            System.out.println(id + ": " + method);
253        }
254    }
255
256    private static void print(String name, Image image) {
257        if (image != null) {
258            System.out.println(name + " icon is exist");
259        }
260    }
261}
262