Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/make/src/classes/build/tools/swingbeaninfo/GenSwingBeanInfo.java
32287 views
1
/*
2
* Copyright (c) 1998, 2013, 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. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package build.tools.swingbeaninfo;
27
28
import java.beans.BeanInfo;
29
import java.beans.BeanDescriptor;
30
import java.beans.Introspector;
31
import java.beans.IntrospectionException;
32
import java.beans.PropertyDescriptor;
33
34
import java.io.*;
35
36
import java.util.Hashtable;
37
import java.util.HashMap;
38
import java.util.Iterator;
39
40
/**
41
* A utlity for generating a BeanInfo source file from a template and a
42
* Hashtable with hints that were generated from a doclet.
43
* it's neccessary to write things like the per property descriptions
44
* by hand. To run the application:
45
* <pre>
46
* java GenSwingBeanInfo <class name>
47
* </pre>
48
* Code for a bean info class is written to out. If the class is
49
* swing package, you don't need to fully specify its name.
50
*
51
* @author Hans Muller
52
* @author Rich Schiavi
53
* @author Mark Davidson
54
*/
55
public class GenSwingBeanInfo {
56
private final static String BEANINFO_SUFFIX = "BeanInfo.java";
57
58
// Tokens in @(...)
59
private final static String TOK_BEANPACKAGE = "BeanPackageName";
60
private final static String TOK_BEANCLASS = "BeanClassName";
61
private final static String TOK_BEANOBJECT = "BeanClassObject";
62
private final static String TOK_CLASSDESC = "ClassDescriptors";
63
private final static String TOK_BEANDESC = "BeanDescription";
64
private final static String TOK_PROPDESC = "BeanPropertyDescriptors";
65
private final static String TOK_ENUMVARS = "EnumVariables";
66
67
private String enumcode; // Generated code for enumerated properties.
68
69
private boolean DEBUG = false;
70
71
private String fileDir;
72
private String templateFilename;
73
74
/**
75
* Public constructor
76
* @param fileDir Location to put the generated source files.
77
* @param templateFilename Location of the BeanInfo template
78
* @param debug Flag to turn on debugging
79
*/
80
public GenSwingBeanInfo(String fileDir, String templateFilename, boolean debug) {
81
this.fileDir = fileDir;
82
this.templateFilename = templateFilename;
83
this.DEBUG = debug;
84
}
85
86
/**
87
* Opens a BeanInfo PrintStream for the class.
88
*/
89
private PrintStream initOutputFile(String classname) {
90
try {
91
OutputStream out = new FileOutputStream(fileDir + File.separator + classname + BEANINFO_SUFFIX);
92
BufferedOutputStream bout = new BufferedOutputStream(out);
93
return new PrintStream(out);
94
} catch (IOException e){
95
// System.err.println("GenSwingBeanInfo: " + e.toString());
96
}
97
return null;
98
}
99
100
private static void messageAndExit(String msg) {
101
System.err.println("\n" + msg);
102
System.exit(1);
103
}
104
105
106
/**
107
* Load the contents of the BeanInfo template into a string and
108
* return the string.
109
*/
110
private String loadTemplate() {
111
String template = "<no template>";
112
113
try {
114
File file = new File(templateFilename);
115
DataInputStream stream = new DataInputStream(new FileInputStream(file));
116
BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
117
StringBuffer buffer = new StringBuffer();
118
119
int c;
120
while((c = reader.read()) != -1) {
121
buffer.append((char)c);
122
}
123
124
template = buffer.toString();
125
reader.close();
126
} catch (IOException e) {
127
System.out.println(e.getMessage());
128
messageAndExit("GenSwingBeanInfo: Couldn't load template: " + templateFilename + e);
129
}
130
return template;
131
}
132
133
134
/**
135
* Generates a string for the BeanDescriptor
136
*/
137
private String genBeanDescriptor(DocBeanInfo dbi) {
138
String code = "";
139
int beanflags = dbi.beanflags;
140
141
// we support export, hidden, preferred
142
if ((beanflags & DocBeanInfo.EXPERT) != 0)
143
code += " sun.swing.BeanInfoUtils.EXPERT, Boolean.TRUE,\n";
144
if ((beanflags & DocBeanInfo.HIDDEN) !=0)
145
code += " sun.swing.BeanInfoUtils.HIDDEN, Boolean.TRUE,\n";
146
/* 1.2 only - make sure build flag build using 1.2 */
147
if ((beanflags & DocBeanInfo.PREFERRED) !=0)
148
code += " sun.swing.BeanInfoUtils.PREFERRED, Boolean.TRUE,\n";
149
if (!(dbi.customizerclass.equals("null")))
150
code += " sun.swing.BeanInfoUtils.CUSTOMIZERCLASS, " + dbi.customizerclass + ".class,\n";
151
152
if (dbi.attribs != null) {
153
code += genAttributes(dbi.attribs);
154
}
155
156
return code;
157
}
158
159
/**
160
* Generates the code for the attributes table.
161
*/
162
private String genAttributes(HashMap attribs) {
163
StringBuffer code = new StringBuffer();
164
String key;
165
String value;
166
167
Iterator iterator = attribs.keySet().iterator();
168
while(iterator.hasNext()) {
169
key = (String)iterator.next();
170
value = (String)attribs.get(key);
171
172
if (value.equals("true") || value.equals("false")) {
173
// Substitute the "true" and "false" for codegen Boolean values.
174
if(value.equals("true"))
175
value = "Boolean.TRUE";
176
else
177
value = "Boolean.FALSE";
178
179
code.append(" \"").append(key).append("\", ").append(value).append(",\n");
180
} else {
181
code.append(" \"").append(key).append("\", \"").append(value).append("\",\n");
182
}
183
}
184
return code.toString();
185
}
186
187
/**
188
* Generates the code for the enumeration.
189
* XXX - side effect: Modifies the enumcode field variable.
190
*/
191
private String genEnumeration(String propName, HashMap enums) {
192
String objectName = propName + "Enumeration";
193
String key;
194
String value;
195
196
StringBuffer code = new StringBuffer("\n\t\tObject[] ");
197
code.append(objectName).append(" = new Object[] { \n");
198
199
Iterator iterator = enums.keySet().iterator();
200
while(iterator.hasNext()) {
201
key = (String)iterator.next();
202
value = (String)enums.get(key);
203
204
code.append("\t\t\t\"").append(key).append("\" , new Integer(");
205
code.append(value).append("), \"").append(value).append("\",\n");
206
}
207
// Close the statically initialized Object[]
208
code.replace(code.length() - 2, code.length(), "\n\t\t};\n");
209
210
// Add this string to the enumeration code.
211
enumcode += code.toString();
212
213
// Return the PropertyDescriptor init string;
214
return " \"enumerationValues\", " + objectName + ",\n";
215
}
216
217
/**
218
* Generate the createPropertyDescriptor() calls, one per property.
219
* A fully specified createPropertyDescriptor() call looks like this:
220
* <pre>
221
* createPropertyDescriptor("contentPane", new Object[] {
222
* BOUND, Boolean.TRUE,
223
* CONSTRAINED, Boolean.TRUE,
224
* PROPERTYEDITORCLASS, package.MyEditor.cl
225
* WRITEMETHOD, "setContentPane",
226
* DISPLAYNAME, "contentPane",
227
* EXPERT, Boolean.FALSE,
228
* HIDDEN, Boolean.FALSE,
229
* PREFERRED, Boolean.TRUE,
230
* SHORTDESCRIPTION, "A top level window with a window manager border",
231
* "random attribute","random value"
232
* }
233
* );
234
* </pre>
235
*
236
* @param info The actual BeanInfo class generated from from the Intospector.
237
* @param dochash Set of DocBeanInfo pairs for each property. This information
238
* is used to suplement the instrospected properties.
239
* @return A snippet of source code which would construct all the PropertyDescriptors.
240
*/
241
private String genPropertyDescriptors(BeanInfo info, Hashtable dochash) {
242
String code = "";
243
enumcode = " "; // code for enumerated properties.
244
PropertyDescriptor[] pds = info.getPropertyDescriptors();
245
boolean hash_match = false;
246
DocBeanInfo dbi = null;
247
248
for(int i = 0; i < pds.length; i++) {
249
if (pds[i].getReadMethod() != null) {
250
code += "\ncreatePropertyDescriptor(\"" + pds[i].getName() + "\", new Object[] {\n";
251
252
if (DEBUG)
253
System.out.println("Introspected propertyDescriptor: " + pds[i].getName());
254
255
if (dochash.size() > 0 && dochash.containsKey(pds[i].getName())) {
256
dbi = (DocBeanInfo)dochash.remove(pds[i].getName());
257
// override/set properties on this *introspected*
258
// BeanInfo pds using our DocBeanInfo class values
259
setDocInfoProps(dbi, pds[i]);
260
hash_match = true;
261
if (DEBUG)
262
System.out.println("DocBeanInfo class exists for propertyDescriptor: " + pds[i].getName() + "\n");
263
} else {
264
hash_match = false;
265
}
266
267
// Do I need to do anything with this property descriptor
268
if (hash_match) {
269
if ((dbi.beanflags & DocBeanInfo.BOUND) != 0) {
270
code += " sun.swing.BeanInfoUtils.BOUND, Boolean.TRUE,\n";
271
} else {
272
code += " sun.swing.BeanInfoUtils.BOUND, Boolean.FALSE,\n";
273
}
274
}
275
276
if (pds[i].isConstrained()) {
277
code += " sun.swing.BeanInfoUtils.CONSTRAINED, Boolean.TRUE,\n";
278
}
279
280
if (pds[i].getPropertyEditorClass() != null) {
281
String className = pds[i].getPropertyEditorClass().getName();
282
code += " sun.swing.BeanInfoUtils.PROPERTYEDITORCLASS, " + className + ".class,\n";
283
} else if ((hash_match) && (!(dbi.propertyeditorclass.equals("null")))) {
284
code += " sun.swing.BeanInfoUtils.PROPERTYEDITORCLASS, " + dbi.propertyeditorclass + ".class,\n";
285
}
286
287
if ((hash_match) && (!(dbi.customizerclass.equals("null")))) {
288
code += " sun.swing.BeanInfoUtils.CUSTOMIZERCLASS, " + dbi.customizerclass + ".class,\n";
289
}
290
291
if ((hash_match) && (dbi.enums != null)) {
292
code += genEnumeration(pds[i].getName(), dbi.enums);
293
}
294
295
if (!pds[i].getDisplayName().equals(pds[i].getName())) {
296
code += " sun.swing.BeanInfoUtils.DISPLAYNAME, \"" + pds[i].getDisplayName() + "\",\n";
297
}
298
299
if (pds[i].isExpert()) {
300
code += " sun.swing.BeanInfoUtils.EXPERT, Boolean.TRUE,\n";
301
}
302
303
if (pds[i].isHidden()) {
304
code += " sun.swing.BeanInfoUtils.HIDDEN, Boolean.TRUE,\n";
305
}
306
307
if (pds[i].isPreferred()) {
308
code += " sun.swing.BeanInfoUtils.PREFERRED, Boolean.TRUE,\n";
309
}
310
311
// user attributes
312
if (hash_match) {
313
if (dbi.attribs != null) {
314
code += genAttributes(dbi.attribs);
315
}
316
}
317
code += " sun.swing.BeanInfoUtils.SHORTDESCRIPTION, \"" + pds[i].getShortDescription() + "\",\n";
318
319
// Print the closing brackets. If this is the last array initializer,
320
// don't print the trailing comma.
321
if (i == (pds.length - 1)) {
322
code += " }\n)\n";
323
} else {
324
code += " }\n),\n";
325
}
326
327
} // end if ( readMethod != null )
328
} // end for
329
return code;
330
}
331
332
/**
333
* Sets properties from the BeanInfo supplement on the
334
* introspected PropertyDescriptor
335
*/
336
private void setDocInfoProps(DocBeanInfo dbi, PropertyDescriptor pds) {
337
int beanflags = dbi.beanflags;
338
339
if ((beanflags & DocBeanInfo.BOUND) != 0)
340
pds.setBound(true);
341
if ((beanflags & DocBeanInfo.EXPERT) != 0)
342
pds.setExpert(true);
343
if ((beanflags & DocBeanInfo.CONSTRAINED) != 0)
344
pds.setConstrained(true);
345
if ((beanflags & DocBeanInfo.HIDDEN) !=0)
346
pds.setHidden(true);
347
if ((beanflags & DocBeanInfo.PREFERRED) !=0)
348
pds.setPreferred(true);
349
350
if (!(dbi.desc.equals("null"))){
351
pds.setShortDescription(dbi.desc);
352
}
353
if (!(dbi.displayname.equals("null"))){
354
pds.setDisplayName(dbi.displayname);
355
}
356
}
357
358
/**
359
* Generates the BeanInfo source file using instrospection and a
360
* Hashtable full of hints. This the only public method in this class.
361
*
362
* @param classname Root name of the class. i.e., JButton
363
* @param dochash A hashtable containing the DocBeanInfo.
364
*/
365
public void genBeanInfo(String packageName, String classname, Hashtable dochash) {
366
// The following initial values are just examples. All of these
367
// fields are initialized below.
368
String beanClassName = "JInternalFrame";
369
String beanClassObject = "javax.swing.JInternalFrame.class";
370
String beanDescription = "<A description of this component>.";
371
String beanPropertyDescriptors = "<createSwingPropertyDescriptor code>";
372
String classPropertyDescriptors = "<createSwingClassPropertyDescriptor code>";
373
374
Class cls = getClass(packageName, classname);
375
if (cls == null){
376
messageAndExit("Can't find class: " + classname);
377
}
378
379
// Get the output stream.
380
PrintStream out = initOutputFile(classname);
381
382
// Run the Introspector and initialize the variables
383
384
BeanInfo beanInfo = null;
385
BeanDescriptor beanDescriptor = null;
386
387
try {
388
if (cls == javax.swing.JComponent.class) {
389
// Go all the way up the heirarchy for JComponent
390
beanInfo = Introspector.getBeanInfo(cls);
391
} else {
392
beanInfo = Introspector.getBeanInfo(cls, cls.getSuperclass());
393
}
394
beanDescriptor = beanInfo.getBeanDescriptor();
395
beanDescription = beanDescriptor.getShortDescription();
396
} catch (IntrospectionException e) {
397
messageAndExit("Introspection failed for " + cls.getName() + " " + e);
398
}
399
400
beanClassName = beanDescriptor.getName();
401
beanClassObject = cls.getName() + ".class";
402
403
if (DEBUG){
404
System.out.println(">>>>GenSwingBeanInfo class: " + beanClassName);
405
}
406
// Generate the Class BeanDescriptor information first
407
if (dochash.size() > 0) {
408
if (dochash.containsKey(beanClassName)) {
409
DocBeanInfo dbi = (DocBeanInfo)dochash.remove(beanClassName);
410
classPropertyDescriptors = genBeanDescriptor(dbi);
411
if (DEBUG)
412
System.out.println("ClassPropertyDescriptors: " + classPropertyDescriptors);
413
if (!(dbi.desc.equals("null")))
414
beanDescription = dbi.desc;
415
} else
416
beanDescription = beanDescriptor.getShortDescription();
417
} else
418
beanDescription = beanDescriptor.getShortDescription();
419
420
// Generate the Property descriptors
421
beanPropertyDescriptors = genPropertyDescriptors(beanInfo,dochash);
422
423
// Dump the template to out, substituting values for
424
// @(token) tokens as they're encountered.
425
426
int currentIndex = 0;
427
// not loading this to get around build issue for now
428
String template = loadTemplate();
429
430
// This loop substitutes the "@(...)" tags in the template with the ones for the
431
// current class.
432
while (currentIndex < template.length()) {
433
// Find the Token
434
int tokenStart = template.indexOf("@(", currentIndex);
435
if (tokenStart != -1) {
436
out.print(template.substring(currentIndex, tokenStart));
437
438
int tokenEnd = template.indexOf(")", tokenStart);
439
if (tokenEnd == -1) {
440
messageAndExit("Bad @(<token>) beginning at " + tokenStart);
441
}
442
String token = template.substring(tokenStart+2, tokenEnd);
443
444
if (token.equals(TOK_BEANCLASS)) {
445
out.print(beanClassName);
446
} else if (token.equals(TOK_CLASSDESC)) {
447
if (!(classPropertyDescriptors.equals("<createSwingClassPropertyDescriptor code>"))) {
448
printDescriptors(out, classPropertyDescriptors, template, tokenStart);
449
}
450
} else if (token.equals(TOK_BEANPACKAGE)){
451
out.print(packageName);
452
} else if (token.equals(TOK_BEANOBJECT)) {
453
out.print(beanClassObject);
454
} else if (token.equals(TOK_BEANDESC)) {
455
out.print(beanDescription);
456
} else if (token.equals(TOK_ENUMVARS)){
457
out.print(enumcode);
458
} else if (token.equals(TOK_PROPDESC)) {
459
printDescriptors(out, beanPropertyDescriptors, template, tokenStart);
460
} else if (token.equals("#")) {
461
// Ignore the @(#) Version Control tag if it exists.
462
} else {
463
messageAndExit("Unrecognized token @(" + token + ")");
464
}
465
currentIndex = tokenEnd + 1;
466
} else {
467
// tokenStart == -1 - We are finsihed.
468
out.print(template.substring(currentIndex, template.length()));
469
break;
470
}
471
}
472
out.close();
473
}
474
475
/**
476
* Returns the class from the package name and the class root name.
477
*
478
* @param packageName The name of the package of the containing class.
479
* @param rootname The root name of the class. i.e, JButton
480
* @return The class instance or null.
481
*/
482
private Class getClass(String packageName, String rootname) {
483
Class cls = null;
484
String classname = rootname;
485
486
if (packageName != null || !packageName.equals("")) {
487
classname = packageName + "." + rootname;
488
}
489
490
try {
491
cls = Class.forName(classname);
492
} catch (ClassNotFoundException e) {
493
// Fail silently.
494
}
495
return cls;
496
}
497
498
/**
499
* Prints the formated descriptors to the PrintStream
500
* @param out Open PrintStream
501
* @param s String descriptor
502
* @param template Template
503
* @param tokenStart Index into the template
504
*/
505
private void printDescriptors(PrintStream out, String s,
506
String template, int tokenStart) {
507
String indent = "";
508
509
// Find the newline that preceeds @(BeanPropertyDescriptors) to
510
// calculate the indent.
511
for (int i = tokenStart; i >= 0; i--) {
512
if (template.charAt(i) == '\n') {
513
char[] chars = new char[tokenStart - i];
514
for (int j = 0; j < chars.length; j++) {
515
chars[j] = ' ';
516
}
517
indent = new String(chars);
518
break;
519
}
520
}
521
522
int i = 0;
523
while(i < s.length()) {
524
int nlIndex = s.indexOf('\n', i);
525
out.print(s.substring(i, nlIndex+1));
526
out.print(indent);
527
i = nlIndex + 1;
528
}
529
}
530
531
532
}
533
534