Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/share/classes/java/beans/MetaData.java
41152 views
1
/*
2
* Copyright (c) 2000, 2021, 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
package java.beans;
26
27
import com.sun.beans.finder.PrimitiveWrapperMap;
28
29
import java.awt.AWTKeyStroke;
30
import java.awt.BorderLayout;
31
import java.awt.Dimension;
32
import java.awt.Color;
33
import java.awt.Font;
34
import java.awt.GridBagConstraints;
35
import java.awt.Insets;
36
import java.awt.Point;
37
import java.awt.Rectangle;
38
import java.awt.event.KeyEvent;
39
import java.awt.font.TextAttribute;
40
41
import java.lang.reflect.Array;
42
import java.lang.reflect.Constructor;
43
import java.lang.reflect.Field;
44
import java.lang.reflect.Method;
45
import java.lang.reflect.Modifier;
46
import java.lang.reflect.InvocationTargetException;
47
48
import java.security.AccessController;
49
import java.security.PrivilegedAction;
50
51
import java.util.*;
52
53
import javax.swing.Box;
54
import javax.swing.JLayeredPane;
55
import javax.swing.border.MatteBorder;
56
import javax.swing.plaf.ColorUIResource;
57
58
import sun.swing.PrintColorUIResource;
59
60
import static sun.reflect.misc.ReflectUtil.isPackageAccessible;
61
62
/*
63
* Like the {@code Intropector}, the {@code MetaData} class
64
* contains <em>meta</em> objects that describe the way
65
* classes should express their state in terms of their
66
* own public APIs.
67
*
68
* @see java.beans.Intropector
69
*
70
* @author Philip Milne
71
* @author Steve Langley
72
*/
73
class MetaData {
74
75
static final class NullPersistenceDelegate extends PersistenceDelegate {
76
// Note this will be called by all classes when they reach the
77
// top of their superclass chain.
78
protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
79
}
80
protected Expression instantiate(Object oldInstance, Encoder out) { return null; }
81
82
public void writeObject(Object oldInstance, Encoder out) {
83
// System.out.println("NullPersistenceDelegate:writeObject " + oldInstance);
84
}
85
}
86
87
/**
88
* The persistence delegate for {@code enum} classes.
89
*
90
* @author Sergey A. Malenkov
91
*/
92
static final class EnumPersistenceDelegate extends PersistenceDelegate {
93
protected boolean mutatesTo(Object oldInstance, Object newInstance) {
94
return oldInstance == newInstance;
95
}
96
97
protected Expression instantiate(Object oldInstance, Encoder out) {
98
Enum<?> e = (Enum<?>) oldInstance;
99
return new Expression(e, Enum.class, "valueOf", new Object[]{e.getDeclaringClass(), e.name()});
100
}
101
}
102
103
static final class PrimitivePersistenceDelegate extends PersistenceDelegate {
104
protected boolean mutatesTo(Object oldInstance, Object newInstance) {
105
return oldInstance.equals(newInstance);
106
}
107
108
protected Expression instantiate(Object oldInstance, Encoder out) {
109
return new Expression(oldInstance, oldInstance.getClass(),
110
"new", new Object[]{oldInstance.toString()});
111
}
112
}
113
114
static final class ArrayPersistenceDelegate extends PersistenceDelegate {
115
protected boolean mutatesTo(Object oldInstance, Object newInstance) {
116
return (newInstance != null &&
117
oldInstance.getClass() == newInstance.getClass() && // Also ensures the subtype is correct.
118
Array.getLength(oldInstance) == Array.getLength(newInstance));
119
}
120
121
protected Expression instantiate(Object oldInstance, Encoder out) {
122
// System.out.println("instantiate: " + type + " " + oldInstance);
123
Class<?> oldClass = oldInstance.getClass();
124
return new Expression(oldInstance, Array.class, "newInstance",
125
new Object[]{oldClass.getComponentType(),
126
Array.getLength(oldInstance)});
127
}
128
129
protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
130
int n = Array.getLength(oldInstance);
131
for (int i = 0; i < n; i++) {
132
Object index = i;
133
// Expression oldGetExp = new Expression(Array.class, "get", new Object[]{oldInstance, index});
134
// Expression newGetExp = new Expression(Array.class, "get", new Object[]{newInstance, index});
135
Expression oldGetExp = new Expression(oldInstance, "get", new Object[]{index});
136
Expression newGetExp = new Expression(newInstance, "get", new Object[]{index});
137
try {
138
Object oldValue = oldGetExp.getValue();
139
Object newValue = newGetExp.getValue();
140
out.writeExpression(oldGetExp);
141
if (!Objects.equals(newValue, out.get(oldValue))) {
142
// System.out.println("Not equal: " + newGetExp + " != " + actualGetExp);
143
// invokeStatement(Array.class, "set", new Object[]{oldInstance, index, oldValue}, out);
144
DefaultPersistenceDelegate.invokeStatement(oldInstance, "set", new Object[]{index, oldValue}, out);
145
}
146
}
147
catch (Exception e) {
148
// System.err.println("Warning:: failed to write: " + oldGetExp);
149
out.getExceptionListener().exceptionThrown(e);
150
}
151
}
152
}
153
}
154
155
static final class ProxyPersistenceDelegate extends PersistenceDelegate {
156
protected Expression instantiate(Object oldInstance, Encoder out) {
157
Class<?> type = oldInstance.getClass();
158
java.lang.reflect.Proxy p = (java.lang.reflect.Proxy)oldInstance;
159
// This unappealing hack is not required but makes the
160
// representation of EventHandlers much more concise.
161
java.lang.reflect.InvocationHandler ih = java.lang.reflect.Proxy.getInvocationHandler(p);
162
if (ih instanceof EventHandler) {
163
EventHandler eh = (EventHandler)ih;
164
Vector<Object> args = new Vector<>();
165
args.add(type.getInterfaces()[0]);
166
args.add(eh.getTarget());
167
args.add(eh.getAction());
168
if (eh.getEventPropertyName() != null) {
169
args.add(eh.getEventPropertyName());
170
}
171
if (eh.getListenerMethodName() != null) {
172
args.setSize(4);
173
args.add(eh.getListenerMethodName());
174
}
175
return new Expression(oldInstance,
176
EventHandler.class,
177
"create",
178
args.toArray());
179
}
180
return new Expression(oldInstance,
181
java.lang.reflect.Proxy.class,
182
"newProxyInstance",
183
new Object[]{type.getClassLoader(),
184
type.getInterfaces(),
185
ih});
186
}
187
}
188
189
// Strings
190
static final class java_lang_String_PersistenceDelegate extends PersistenceDelegate {
191
protected Expression instantiate(Object oldInstance, Encoder out) { return null; }
192
193
public void writeObject(Object oldInstance, Encoder out) {
194
// System.out.println("NullPersistenceDelegate:writeObject " + oldInstance);
195
}
196
}
197
198
// Classes
199
static final class java_lang_Class_PersistenceDelegate extends PersistenceDelegate {
200
protected boolean mutatesTo(Object oldInstance, Object newInstance) {
201
return oldInstance.equals(newInstance);
202
}
203
204
protected Expression instantiate(Object oldInstance, Encoder out) {
205
Class<?> c = (Class)oldInstance;
206
// As of 1.3 it is not possible to call Class.forName("int"),
207
// so we have to generate different code for primitive types.
208
// This is needed for arrays whose subtype may be primitive.
209
if (c.isPrimitive()) {
210
Field field = null;
211
try {
212
field = PrimitiveWrapperMap.getType(c.getName()).getDeclaredField("TYPE");
213
} catch (NoSuchFieldException ex) {
214
System.err.println("Unknown primitive type: " + c);
215
}
216
return new Expression(oldInstance, field, "get", new Object[]{null});
217
}
218
else if (oldInstance == String.class) {
219
return new Expression(oldInstance, "", "getClass", new Object[]{});
220
}
221
else if (oldInstance == Class.class) {
222
return new Expression(oldInstance, String.class, "getClass", new Object[]{});
223
}
224
else {
225
Expression newInstance = new Expression(oldInstance, Class.class, "forName", new Object[] { c.getName() });
226
newInstance.loader = c.getClassLoader();
227
return newInstance;
228
}
229
}
230
}
231
232
// Fields
233
static final class java_lang_reflect_Field_PersistenceDelegate extends PersistenceDelegate {
234
protected boolean mutatesTo(Object oldInstance, Object newInstance) {
235
return oldInstance.equals(newInstance);
236
}
237
238
protected Expression instantiate(Object oldInstance, Encoder out) {
239
Field f = (Field)oldInstance;
240
return new Expression(oldInstance,
241
f.getDeclaringClass(),
242
"getField",
243
new Object[]{f.getName()});
244
}
245
}
246
247
// Methods
248
static final class java_lang_reflect_Method_PersistenceDelegate extends PersistenceDelegate {
249
protected boolean mutatesTo(Object oldInstance, Object newInstance) {
250
return oldInstance.equals(newInstance);
251
}
252
253
protected Expression instantiate(Object oldInstance, Encoder out) {
254
Method m = (Method)oldInstance;
255
return new Expression(oldInstance,
256
m.getDeclaringClass(),
257
"getMethod",
258
new Object[]{m.getName(), m.getParameterTypes()});
259
}
260
}
261
262
// Dates
263
264
/**
265
* The persistence delegate for {@code java.util.Date} classes.
266
* Do not extend DefaultPersistenceDelegate to improve performance and
267
* to avoid problems with {@code java.sql.Date},
268
* {@code java.sql.Time} and {@code java.sql.Timestamp}.
269
*
270
* @author Sergey A. Malenkov
271
*/
272
static class java_util_Date_PersistenceDelegate extends PersistenceDelegate {
273
protected boolean mutatesTo(Object oldInstance, Object newInstance) {
274
if (!super.mutatesTo(oldInstance, newInstance)) {
275
return false;
276
}
277
Date oldDate = (Date)oldInstance;
278
Date newDate = (Date)newInstance;
279
280
return oldDate.getTime() == newDate.getTime();
281
}
282
283
protected Expression instantiate(Object oldInstance, Encoder out) {
284
Date date = (Date)oldInstance;
285
return new Expression(date, date.getClass(), "new", new Object[] {date.getTime()});
286
}
287
}
288
289
/**
290
* The persistence delegate for {@code java.sql.Timestamp} classes.
291
* It supports nanoseconds.
292
*
293
* @author Sergey A. Malenkov
294
*/
295
static final class java_sql_Timestamp_PersistenceDelegate extends java_util_Date_PersistenceDelegate {
296
private static final Method getNanosMethod = getNanosMethod();
297
298
private static Method getNanosMethod() {
299
try {
300
Class<?> c = Class.forName("java.sql.Timestamp", true, ClassLoader.getPlatformClassLoader());
301
return c.getMethod("getNanos");
302
} catch (ClassNotFoundException e) {
303
return null;
304
} catch (NoSuchMethodException e) {
305
throw new AssertionError(e);
306
}
307
}
308
309
/**
310
* Invoke Timstamp getNanos.
311
*/
312
private static int getNanos(Object obj) {
313
if (getNanosMethod == null)
314
throw new AssertionError("Should not get here");
315
try {
316
return (Integer)getNanosMethod.invoke(obj);
317
} catch (InvocationTargetException e) {
318
Throwable cause = e.getCause();
319
if (cause instanceof RuntimeException)
320
throw (RuntimeException)cause;
321
if (cause instanceof Error)
322
throw (Error)cause;
323
throw new AssertionError(e);
324
} catch (IllegalAccessException iae) {
325
throw new AssertionError(iae);
326
}
327
}
328
329
protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
330
// assumes oldInstance and newInstance are Timestamps
331
int nanos = getNanos(oldInstance);
332
if (nanos != getNanos(newInstance)) {
333
out.writeStatement(new Statement(oldInstance, "setNanos", new Object[] {nanos}));
334
}
335
}
336
}
337
338
// Collections
339
340
/*
341
The Hashtable and AbstractMap classes have no common ancestor yet may
342
be handled with a single persistence delegate: one which uses the methods
343
of the Map insterface exclusively. Attatching the persistence delegates
344
to the interfaces themselves is fraught however since, in the case of
345
the Map, both the AbstractMap and HashMap classes are declared to
346
implement the Map interface, leaving the obvious implementation prone
347
to repeating their initialization. These issues and questions around
348
the ordering of delegates attached to interfaces have lead us to
349
ignore any delegates attached to interfaces and force all persistence
350
delegates to be registered with concrete classes.
351
*/
352
353
/**
354
* The base class for persistence delegates for inner classes
355
* that can be created using {@link Collections}.
356
*
357
* @author Sergey A. Malenkov
358
*/
359
private abstract static class java_util_Collections extends PersistenceDelegate {
360
protected boolean mutatesTo(Object oldInstance, Object newInstance) {
361
if (!super.mutatesTo(oldInstance, newInstance)) {
362
return false;
363
}
364
if ((oldInstance instanceof List) || (oldInstance instanceof Set) || (oldInstance instanceof Map)) {
365
return oldInstance.equals(newInstance);
366
}
367
Collection<?> oldC = (Collection<?>) oldInstance;
368
Collection<?> newC = (Collection<?>) newInstance;
369
return (oldC.size() == newC.size()) && oldC.containsAll(newC);
370
}
371
372
protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
373
// do not initialize these custom collections in default way
374
}
375
376
static final class EmptyList_PersistenceDelegate extends java_util_Collections {
377
protected Expression instantiate(Object oldInstance, Encoder out) {
378
return new Expression(oldInstance, Collections.class, "emptyList", null);
379
}
380
}
381
382
static final class EmptySet_PersistenceDelegate extends java_util_Collections {
383
protected Expression instantiate(Object oldInstance, Encoder out) {
384
return new Expression(oldInstance, Collections.class, "emptySet", null);
385
}
386
}
387
388
static final class EmptyMap_PersistenceDelegate extends java_util_Collections {
389
protected Expression instantiate(Object oldInstance, Encoder out) {
390
return new Expression(oldInstance, Collections.class, "emptyMap", null);
391
}
392
}
393
394
static final class SingletonList_PersistenceDelegate extends java_util_Collections {
395
protected Expression instantiate(Object oldInstance, Encoder out) {
396
List<?> list = (List<?>) oldInstance;
397
return new Expression(oldInstance, Collections.class, "singletonList", new Object[]{list.get(0)});
398
}
399
}
400
401
static final class SingletonSet_PersistenceDelegate extends java_util_Collections {
402
protected Expression instantiate(Object oldInstance, Encoder out) {
403
Set<?> set = (Set<?>) oldInstance;
404
return new Expression(oldInstance, Collections.class, "singleton", new Object[]{set.iterator().next()});
405
}
406
}
407
408
static final class SingletonMap_PersistenceDelegate extends java_util_Collections {
409
protected Expression instantiate(Object oldInstance, Encoder out) {
410
Map<?,?> map = (Map<?,?>) oldInstance;
411
Object key = map.keySet().iterator().next();
412
return new Expression(oldInstance, Collections.class, "singletonMap", new Object[]{key, map.get(key)});
413
}
414
}
415
416
static final class UnmodifiableCollection_PersistenceDelegate extends java_util_Collections {
417
protected Expression instantiate(Object oldInstance, Encoder out) {
418
List<?> list = new ArrayList<>((Collection<?>) oldInstance);
419
return new Expression(oldInstance, Collections.class, "unmodifiableCollection", new Object[]{list});
420
}
421
}
422
423
static final class UnmodifiableList_PersistenceDelegate extends java_util_Collections {
424
protected Expression instantiate(Object oldInstance, Encoder out) {
425
List<?> list = new LinkedList<>((Collection<?>) oldInstance);
426
return new Expression(oldInstance, Collections.class, "unmodifiableList", new Object[]{list});
427
}
428
}
429
430
static final class UnmodifiableRandomAccessList_PersistenceDelegate extends java_util_Collections {
431
protected Expression instantiate(Object oldInstance, Encoder out) {
432
List<?> list = new ArrayList<>((Collection<?>) oldInstance);
433
return new Expression(oldInstance, Collections.class, "unmodifiableList", new Object[]{list});
434
}
435
}
436
437
static final class UnmodifiableSet_PersistenceDelegate extends java_util_Collections {
438
protected Expression instantiate(Object oldInstance, Encoder out) {
439
Set<?> set = new HashSet<>((Set<?>) oldInstance);
440
return new Expression(oldInstance, Collections.class, "unmodifiableSet", new Object[]{set});
441
}
442
}
443
444
static final class UnmodifiableSortedSet_PersistenceDelegate extends java_util_Collections {
445
protected Expression instantiate(Object oldInstance, Encoder out) {
446
SortedSet<?> set = new TreeSet<>((SortedSet<?>) oldInstance);
447
return new Expression(oldInstance, Collections.class, "unmodifiableSortedSet", new Object[]{set});
448
}
449
}
450
451
static final class UnmodifiableMap_PersistenceDelegate extends java_util_Collections {
452
protected Expression instantiate(Object oldInstance, Encoder out) {
453
Map<?,?> map = new HashMap<>((Map<?,?>) oldInstance);
454
return new Expression(oldInstance, Collections.class, "unmodifiableMap", new Object[]{map});
455
}
456
}
457
458
static final class UnmodifiableSortedMap_PersistenceDelegate extends java_util_Collections {
459
protected Expression instantiate(Object oldInstance, Encoder out) {
460
SortedMap<?,?> map = new TreeMap<>((SortedMap<?,?>) oldInstance);
461
return new Expression(oldInstance, Collections.class, "unmodifiableSortedMap", new Object[]{map});
462
}
463
}
464
465
static final class SynchronizedCollection_PersistenceDelegate extends java_util_Collections {
466
protected Expression instantiate(Object oldInstance, Encoder out) {
467
List<?> list = new ArrayList<>((Collection<?>) oldInstance);
468
return new Expression(oldInstance, Collections.class, "synchronizedCollection", new Object[]{list});
469
}
470
}
471
472
static final class SynchronizedList_PersistenceDelegate extends java_util_Collections {
473
protected Expression instantiate(Object oldInstance, Encoder out) {
474
List<?> list = new LinkedList<>((Collection<?>) oldInstance);
475
return new Expression(oldInstance, Collections.class, "synchronizedList", new Object[]{list});
476
}
477
}
478
479
static final class SynchronizedRandomAccessList_PersistenceDelegate extends java_util_Collections {
480
protected Expression instantiate(Object oldInstance, Encoder out) {
481
List<?> list = new ArrayList<>((Collection<?>) oldInstance);
482
return new Expression(oldInstance, Collections.class, "synchronizedList", new Object[]{list});
483
}
484
}
485
486
static final class SynchronizedSet_PersistenceDelegate extends java_util_Collections {
487
protected Expression instantiate(Object oldInstance, Encoder out) {
488
Set<?> set = new HashSet<>((Set<?>) oldInstance);
489
return new Expression(oldInstance, Collections.class, "synchronizedSet", new Object[]{set});
490
}
491
}
492
493
static final class SynchronizedSortedSet_PersistenceDelegate extends java_util_Collections {
494
protected Expression instantiate(Object oldInstance, Encoder out) {
495
SortedSet<?> set = new TreeSet<>((SortedSet<?>) oldInstance);
496
return new Expression(oldInstance, Collections.class, "synchronizedSortedSet", new Object[]{set});
497
}
498
}
499
500
static final class SynchronizedMap_PersistenceDelegate extends java_util_Collections {
501
protected Expression instantiate(Object oldInstance, Encoder out) {
502
Map<?,?> map = new HashMap<>((Map<?,?>) oldInstance);
503
return new Expression(oldInstance, Collections.class, "synchronizedMap", new Object[]{map});
504
}
505
}
506
507
static final class SynchronizedSortedMap_PersistenceDelegate extends java_util_Collections {
508
protected Expression instantiate(Object oldInstance, Encoder out) {
509
SortedMap<?,?> map = new TreeMap<>((SortedMap<?,?>) oldInstance);
510
return new Expression(oldInstance, Collections.class, "synchronizedSortedMap", new Object[]{map});
511
}
512
}
513
}
514
515
// Collection
516
static class java_util_Collection_PersistenceDelegate extends DefaultPersistenceDelegate {
517
protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
518
java.util.Collection<?> oldO = (java.util.Collection)oldInstance;
519
java.util.Collection<?> newO = (java.util.Collection)newInstance;
520
521
if (newO.size() != 0) {
522
invokeStatement(oldInstance, "clear", new Object[]{}, out);
523
}
524
for (Iterator<?> i = oldO.iterator(); i.hasNext();) {
525
invokeStatement(oldInstance, "add", new Object[]{i.next()}, out);
526
}
527
}
528
}
529
530
// List
531
static class java_util_List_PersistenceDelegate extends DefaultPersistenceDelegate {
532
protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
533
java.util.List<?> oldO = (java.util.List<?>)oldInstance;
534
java.util.List<?> newO = (java.util.List<?>)newInstance;
535
int oldSize = oldO.size();
536
int newSize = (newO == null) ? 0 : newO.size();
537
if (oldSize < newSize) {
538
invokeStatement(oldInstance, "clear", new Object[]{}, out);
539
newSize = 0;
540
}
541
for (int i = 0; i < newSize; i++) {
542
Object index = i;
543
544
Expression oldGetExp = new Expression(oldInstance, "get", new Object[]{index});
545
Expression newGetExp = new Expression(newInstance, "get", new Object[]{index});
546
try {
547
Object oldValue = oldGetExp.getValue();
548
Object newValue = newGetExp.getValue();
549
out.writeExpression(oldGetExp);
550
if (!Objects.equals(newValue, out.get(oldValue))) {
551
invokeStatement(oldInstance, "set", new Object[]{index, oldValue}, out);
552
}
553
}
554
catch (Exception e) {
555
out.getExceptionListener().exceptionThrown(e);
556
}
557
}
558
for (int i = newSize; i < oldSize; i++) {
559
invokeStatement(oldInstance, "add", new Object[]{oldO.get(i)}, out);
560
}
561
}
562
}
563
564
565
// Map
566
static class java_util_Map_PersistenceDelegate extends DefaultPersistenceDelegate {
567
protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
568
// System.out.println("Initializing: " + newInstance);
569
java.util.Map<?,?> oldMap = (java.util.Map)oldInstance;
570
java.util.Map<?,?> newMap = (java.util.Map)newInstance;
571
// Remove the new elements.
572
// Do this first otherwise we undo the adding work.
573
if (newMap != null) {
574
for (Object newKey : newMap.keySet().toArray()) {
575
// PENDING: This "key" is not in the right environment.
576
if (!oldMap.containsKey(newKey)) {
577
invokeStatement(oldInstance, "remove", new Object[]{newKey}, out);
578
}
579
}
580
}
581
// Add the new elements.
582
for ( Object oldKey : oldMap.keySet() ) {
583
Expression oldGetExp = new Expression(oldInstance, "get", new Object[]{oldKey});
584
// Pending: should use newKey.
585
Expression newGetExp = new Expression(newInstance, "get", new Object[]{oldKey});
586
try {
587
Object oldValue = oldGetExp.getValue();
588
Object newValue = newGetExp.getValue();
589
out.writeExpression(oldGetExp);
590
if (!Objects.equals(newValue, out.get(oldValue))) {
591
invokeStatement(oldInstance, "put", new Object[]{oldKey, oldValue}, out);
592
} else if ((newValue == null) && !newMap.containsKey(oldKey)) {
593
// put oldValue(=null?) if oldKey is absent in newMap
594
invokeStatement(oldInstance, "put", new Object[]{oldKey, oldValue}, out);
595
}
596
}
597
catch (Exception e) {
598
out.getExceptionListener().exceptionThrown(e);
599
}
600
}
601
}
602
}
603
604
static final class java_util_AbstractCollection_PersistenceDelegate extends java_util_Collection_PersistenceDelegate {}
605
static final class java_util_AbstractList_PersistenceDelegate extends java_util_List_PersistenceDelegate {}
606
static final class java_util_AbstractMap_PersistenceDelegate extends java_util_Map_PersistenceDelegate {}
607
static final class java_util_Hashtable_PersistenceDelegate extends java_util_Map_PersistenceDelegate {}
608
609
610
// Beans
611
static final class java_beans_beancontext_BeanContextSupport_PersistenceDelegate extends java_util_Collection_PersistenceDelegate {}
612
613
// AWT
614
615
/**
616
* The persistence delegate for {@link Insets}.
617
* It is impossible to use {@link DefaultPersistenceDelegate}
618
* because this class does not have any properties.
619
*
620
* @author Sergey A. Malenkov
621
*/
622
static final class java_awt_Insets_PersistenceDelegate extends PersistenceDelegate {
623
protected boolean mutatesTo(Object oldInstance, Object newInstance) {
624
return oldInstance.equals(newInstance);
625
}
626
627
protected Expression instantiate(Object oldInstance, Encoder out) {
628
Insets insets = (Insets) oldInstance;
629
Object[] args = new Object[] {
630
insets.top,
631
insets.left,
632
insets.bottom,
633
insets.right,
634
};
635
return new Expression(insets, insets.getClass(), "new", args);
636
}
637
}
638
639
/**
640
* The persistence delegate for {@link Font}.
641
* It is impossible to use {@link DefaultPersistenceDelegate}
642
* because size of the font can be float value.
643
*
644
* @author Sergey A. Malenkov
645
*/
646
static final class java_awt_Font_PersistenceDelegate extends PersistenceDelegate {
647
protected boolean mutatesTo(Object oldInstance, Object newInstance) {
648
return oldInstance.equals(newInstance);
649
}
650
651
protected Expression instantiate(Object oldInstance, Encoder out) {
652
Font font = (Font) oldInstance;
653
654
int count = 0;
655
String family = null;
656
int style = Font.PLAIN;
657
int size = 12;
658
659
Map<TextAttribute, ?> basic = font.getAttributes();
660
Map<TextAttribute, Object> clone = new HashMap<>(basic.size());
661
for (TextAttribute key : basic.keySet()) {
662
Object value = basic.get(key);
663
if (value != null) {
664
clone.put(key, value);
665
}
666
if (key == TextAttribute.FAMILY) {
667
if (value instanceof String) {
668
count++;
669
family = (String) value;
670
}
671
}
672
else if (key == TextAttribute.WEIGHT) {
673
if (TextAttribute.WEIGHT_REGULAR.equals(value)) {
674
count++;
675
} else if (TextAttribute.WEIGHT_BOLD.equals(value)) {
676
count++;
677
style |= Font.BOLD;
678
}
679
}
680
else if (key == TextAttribute.POSTURE) {
681
if (TextAttribute.POSTURE_REGULAR.equals(value)) {
682
count++;
683
} else if (TextAttribute.POSTURE_OBLIQUE.equals(value)) {
684
count++;
685
style |= Font.ITALIC;
686
}
687
} else if (key == TextAttribute.SIZE) {
688
if (value instanceof Number) {
689
Number number = (Number) value;
690
size = number.intValue();
691
if (size == number.floatValue()) {
692
count++;
693
}
694
}
695
}
696
}
697
Class<?> type = font.getClass();
698
if (count == clone.size()) {
699
return new Expression(font, type, "new", new Object[]{family, style, size});
700
}
701
if (type == Font.class) {
702
return new Expression(font, type, "getFont", new Object[]{clone});
703
}
704
return new Expression(font, type, "new", new Object[]{Font.getFont(clone)});
705
}
706
}
707
708
/**
709
* The persistence delegate for {@link AWTKeyStroke}.
710
* It is impossible to use {@link DefaultPersistenceDelegate}
711
* because this class have no public constructor.
712
*
713
* @author Sergey A. Malenkov
714
*/
715
static final class java_awt_AWTKeyStroke_PersistenceDelegate extends PersistenceDelegate {
716
protected boolean mutatesTo(Object oldInstance, Object newInstance) {
717
return oldInstance.equals(newInstance);
718
}
719
720
protected Expression instantiate(Object oldInstance, Encoder out) {
721
AWTKeyStroke key = (AWTKeyStroke) oldInstance;
722
723
char ch = key.getKeyChar();
724
int code = key.getKeyCode();
725
int mask = key.getModifiers();
726
boolean onKeyRelease = key.isOnKeyRelease();
727
728
Object[] args = null;
729
if (ch == KeyEvent.CHAR_UNDEFINED) {
730
args = !onKeyRelease
731
? new Object[]{code, mask}
732
: new Object[]{code, mask, onKeyRelease};
733
} else if (code == KeyEvent.VK_UNDEFINED) {
734
if (!onKeyRelease) {
735
args = (mask == 0)
736
? new Object[]{ch}
737
: new Object[]{ch, mask};
738
} else if (mask == 0) {
739
args = new Object[]{ch, onKeyRelease};
740
}
741
}
742
if (args == null) {
743
throw new IllegalStateException("Unsupported KeyStroke: " + key);
744
}
745
Class<?> type = key.getClass();
746
String name = type.getName();
747
// get short name of the class
748
int index = name.lastIndexOf('.') + 1;
749
if (index > 0) {
750
name = name.substring(index);
751
}
752
return new Expression( key, type, "get" + name, args );
753
}
754
}
755
756
static class StaticFieldsPersistenceDelegate extends PersistenceDelegate {
757
protected void installFields(Encoder out, Class<?> cls) {
758
if (Modifier.isPublic(cls.getModifiers()) && isPackageAccessible(cls)) {
759
Field[] fields = cls.getFields();
760
for(int i = 0; i < fields.length; i++) {
761
Field field = fields[i];
762
// Don't install primitives, their identity will not be preserved
763
// by wrapping.
764
if (Object.class.isAssignableFrom(field.getType())) {
765
out.writeExpression(new Expression(field, "get", new Object[]{null}));
766
}
767
}
768
}
769
}
770
771
protected Expression instantiate(Object oldInstance, Encoder out) {
772
throw new RuntimeException("Unrecognized instance: " + oldInstance);
773
}
774
775
public void writeObject(Object oldInstance, Encoder out) {
776
if (out.getAttribute(this) == null) {
777
out.setAttribute(this, Boolean.TRUE);
778
installFields(out, oldInstance.getClass());
779
}
780
super.writeObject(oldInstance, out);
781
}
782
}
783
784
// SystemColor
785
static final class java_awt_SystemColor_PersistenceDelegate extends StaticFieldsPersistenceDelegate {}
786
787
// TextAttribute
788
static final class java_awt_font_TextAttribute_PersistenceDelegate extends StaticFieldsPersistenceDelegate {}
789
790
// MenuShortcut
791
static final class java_awt_MenuShortcut_PersistenceDelegate extends PersistenceDelegate {
792
protected boolean mutatesTo(Object oldInstance, Object newInstance) {
793
return oldInstance.equals(newInstance);
794
}
795
796
protected Expression instantiate(Object oldInstance, Encoder out) {
797
java.awt.MenuShortcut m = (java.awt.MenuShortcut)oldInstance;
798
return new Expression(oldInstance, m.getClass(), "new",
799
new Object[]{m.getKey(), Boolean.valueOf(m.usesShiftModifier())});
800
}
801
}
802
803
// Component
804
static final class java_awt_Component_PersistenceDelegate extends DefaultPersistenceDelegate {
805
protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
806
super.initialize(type, oldInstance, newInstance, out);
807
java.awt.Component c = (java.awt.Component)oldInstance;
808
java.awt.Component c2 = (java.awt.Component)newInstance;
809
// The "background", "foreground" and "font" properties.
810
// The foreground and font properties of Windows change from
811
// null to defined values after the Windows are made visible -
812
// special case them for now.
813
if (!(oldInstance instanceof java.awt.Window)) {
814
Object oldBackground = c.isBackgroundSet() ? c.getBackground() : null;
815
Object newBackground = c2.isBackgroundSet() ? c2.getBackground() : null;
816
if (!Objects.equals(oldBackground, newBackground)) {
817
invokeStatement(oldInstance, "setBackground", new Object[] { oldBackground }, out);
818
}
819
Object oldForeground = c.isForegroundSet() ? c.getForeground() : null;
820
Object newForeground = c2.isForegroundSet() ? c2.getForeground() : null;
821
if (!Objects.equals(oldForeground, newForeground)) {
822
invokeStatement(oldInstance, "setForeground", new Object[] { oldForeground }, out);
823
}
824
Object oldFont = c.isFontSet() ? c.getFont() : null;
825
Object newFont = c2.isFontSet() ? c2.getFont() : null;
826
if (!Objects.equals(oldFont, newFont)) {
827
invokeStatement(oldInstance, "setFont", new Object[] { oldFont }, out);
828
}
829
}
830
831
// Bounds
832
java.awt.Container p = c.getParent();
833
if (p == null || p.getLayout() == null) {
834
// Use the most concise construct.
835
boolean locationCorrect = c.getLocation().equals(c2.getLocation());
836
boolean sizeCorrect = c.getSize().equals(c2.getSize());
837
if (!locationCorrect && !sizeCorrect) {
838
invokeStatement(oldInstance, "setBounds", new Object[]{c.getBounds()}, out);
839
}
840
else if (!locationCorrect) {
841
invokeStatement(oldInstance, "setLocation", new Object[]{c.getLocation()}, out);
842
}
843
else if (!sizeCorrect) {
844
invokeStatement(oldInstance, "setSize", new Object[]{c.getSize()}, out);
845
}
846
}
847
}
848
}
849
850
// Container
851
static final class java_awt_Container_PersistenceDelegate extends DefaultPersistenceDelegate {
852
protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
853
super.initialize(type, oldInstance, newInstance, out);
854
// Ignore the children of a JScrollPane.
855
// Pending(milne) find a better way to do this.
856
if (oldInstance instanceof javax.swing.JScrollPane) {
857
return;
858
}
859
java.awt.Container oldC = (java.awt.Container)oldInstance;
860
java.awt.Component[] oldChildren = oldC.getComponents();
861
java.awt.Container newC = (java.awt.Container)newInstance;
862
java.awt.Component[] newChildren = (newC == null) ? new java.awt.Component[0] : newC.getComponents();
863
864
BorderLayout layout = ( oldC.getLayout() instanceof BorderLayout )
865
? ( BorderLayout )oldC.getLayout()
866
: null;
867
868
JLayeredPane oldLayeredPane = (oldInstance instanceof JLayeredPane)
869
? (JLayeredPane) oldInstance
870
: null;
871
872
// Pending. Assume all the new children are unaltered.
873
for(int i = newChildren.length; i < oldChildren.length; i++) {
874
Object[] args = ( layout != null )
875
? new Object[] {oldChildren[i], layout.getConstraints( oldChildren[i] )}
876
: (oldLayeredPane != null)
877
? new Object[] {oldChildren[i], oldLayeredPane.getLayer(oldChildren[i]), Integer.valueOf(-1)}
878
: new Object[] {oldChildren[i]};
879
880
invokeStatement(oldInstance, "add", args, out);
881
}
882
}
883
}
884
885
// Choice
886
static final class java_awt_Choice_PersistenceDelegate extends DefaultPersistenceDelegate {
887
protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
888
super.initialize(type, oldInstance, newInstance, out);
889
java.awt.Choice m = (java.awt.Choice)oldInstance;
890
java.awt.Choice n = (java.awt.Choice)newInstance;
891
for (int i = n.getItemCount(); i < m.getItemCount(); i++) {
892
invokeStatement(oldInstance, "add", new Object[]{m.getItem(i)}, out);
893
}
894
}
895
}
896
897
// Menu
898
static final class java_awt_Menu_PersistenceDelegate extends DefaultPersistenceDelegate {
899
protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
900
super.initialize(type, oldInstance, newInstance, out);
901
java.awt.Menu m = (java.awt.Menu)oldInstance;
902
java.awt.Menu n = (java.awt.Menu)newInstance;
903
for (int i = n.getItemCount(); i < m.getItemCount(); i++) {
904
invokeStatement(oldInstance, "add", new Object[]{m.getItem(i)}, out);
905
}
906
}
907
}
908
909
// MenuBar
910
static final class java_awt_MenuBar_PersistenceDelegate extends DefaultPersistenceDelegate {
911
protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
912
super.initialize(type, oldInstance, newInstance, out);
913
java.awt.MenuBar m = (java.awt.MenuBar)oldInstance;
914
java.awt.MenuBar n = (java.awt.MenuBar)newInstance;
915
for (int i = n.getMenuCount(); i < m.getMenuCount(); i++) {
916
invokeStatement(oldInstance, "add", new Object[]{m.getMenu(i)}, out);
917
}
918
}
919
}
920
921
// List
922
static final class java_awt_List_PersistenceDelegate extends DefaultPersistenceDelegate {
923
protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
924
super.initialize(type, oldInstance, newInstance, out);
925
java.awt.List m = (java.awt.List)oldInstance;
926
java.awt.List n = (java.awt.List)newInstance;
927
for (int i = n.getItemCount(); i < m.getItemCount(); i++) {
928
invokeStatement(oldInstance, "add", new Object[]{m.getItem(i)}, out);
929
}
930
}
931
}
932
933
934
// LayoutManagers
935
936
// BorderLayout
937
static final class java_awt_BorderLayout_PersistenceDelegate extends DefaultPersistenceDelegate {
938
private static final String[] CONSTRAINTS = {
939
BorderLayout.NORTH,
940
BorderLayout.SOUTH,
941
BorderLayout.EAST,
942
BorderLayout.WEST,
943
BorderLayout.CENTER,
944
BorderLayout.PAGE_START,
945
BorderLayout.PAGE_END,
946
BorderLayout.LINE_START,
947
BorderLayout.LINE_END,
948
};
949
@Override
950
protected void initialize(Class<?> type, Object oldInstance,
951
Object newInstance, Encoder out) {
952
super.initialize(type, oldInstance, newInstance, out);
953
BorderLayout oldLayout = (BorderLayout) oldInstance;
954
BorderLayout newLayout = (BorderLayout) newInstance;
955
for (String constraints : CONSTRAINTS) {
956
Object oldC = oldLayout.getLayoutComponent(constraints);
957
Object newC = newLayout.getLayoutComponent(constraints);
958
// Pending, assume any existing elements are OK.
959
if (oldC != null && newC == null) {
960
invokeStatement(oldInstance, "addLayoutComponent",
961
new Object[] { oldC, constraints }, out);
962
}
963
}
964
}
965
}
966
967
// CardLayout
968
static final class java_awt_CardLayout_PersistenceDelegate extends DefaultPersistenceDelegate {
969
protected void initialize(Class<?> type, Object oldInstance,
970
Object newInstance, Encoder out) {
971
super.initialize(type, oldInstance, newInstance, out);
972
if (getVector(newInstance).isEmpty()) {
973
for (Object card : getVector(oldInstance)) {
974
Object[] args = {MetaData.getPrivateFieldValue(card, "java.awt.CardLayout$Card.name"),
975
MetaData.getPrivateFieldValue(card, "java.awt.CardLayout$Card.comp")};
976
invokeStatement(oldInstance, "addLayoutComponent", args, out);
977
}
978
}
979
}
980
protected boolean mutatesTo(Object oldInstance, Object newInstance) {
981
return super.mutatesTo(oldInstance, newInstance) && getVector(newInstance).isEmpty();
982
}
983
private static Vector<?> getVector(Object instance) {
984
return (Vector<?>) MetaData.getPrivateFieldValue(instance, "java.awt.CardLayout.vector");
985
}
986
}
987
988
// GridBagLayout
989
static final class java_awt_GridBagLayout_PersistenceDelegate extends DefaultPersistenceDelegate {
990
protected void initialize(Class<?> type, Object oldInstance,
991
Object newInstance, Encoder out) {
992
super.initialize(type, oldInstance, newInstance, out);
993
if (getHashtable(newInstance).isEmpty()) {
994
for (Map.Entry<?,?> entry : getHashtable(oldInstance).entrySet()) {
995
Object[] args = {entry.getKey(), entry.getValue()};
996
invokeStatement(oldInstance, "addLayoutComponent", args, out);
997
}
998
}
999
}
1000
protected boolean mutatesTo(Object oldInstance, Object newInstance) {
1001
return super.mutatesTo(oldInstance, newInstance) && getHashtable(newInstance).isEmpty();
1002
}
1003
private static Hashtable<?,?> getHashtable(Object instance) {
1004
return (Hashtable<?,?>) MetaData.getPrivateFieldValue(instance, "java.awt.GridBagLayout.comptable");
1005
}
1006
}
1007
1008
// Swing
1009
1010
// JFrame (If we do this for Window instead of JFrame, the setVisible call
1011
// will be issued before we have added all the children to the JFrame and
1012
// will appear blank).
1013
static final class javax_swing_JFrame_PersistenceDelegate extends DefaultPersistenceDelegate {
1014
protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
1015
super.initialize(type, oldInstance, newInstance, out);
1016
java.awt.Window oldC = (java.awt.Window)oldInstance;
1017
java.awt.Window newC = (java.awt.Window)newInstance;
1018
boolean oldV = oldC.isVisible();
1019
boolean newV = newC.isVisible();
1020
if (newV != oldV) {
1021
// false means: don't execute this statement at write time.
1022
boolean executeStatements = out.executeStatements;
1023
out.executeStatements = false;
1024
invokeStatement(oldInstance, "setVisible", new Object[]{Boolean.valueOf(oldV)}, out);
1025
out.executeStatements = executeStatements;
1026
}
1027
}
1028
}
1029
1030
// Models
1031
1032
// DefaultListModel
1033
static final class javax_swing_DefaultListModel_PersistenceDelegate extends DefaultPersistenceDelegate {
1034
protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
1035
// Note, the "size" property will be set here.
1036
super.initialize(type, oldInstance, newInstance, out);
1037
javax.swing.DefaultListModel<?> m = (javax.swing.DefaultListModel<?>)oldInstance;
1038
javax.swing.DefaultListModel<?> n = (javax.swing.DefaultListModel<?>)newInstance;
1039
for (int i = n.getSize(); i < m.getSize(); i++) {
1040
invokeStatement(oldInstance, "add", // Can also use "addElement".
1041
new Object[]{m.getElementAt(i)}, out);
1042
}
1043
}
1044
}
1045
1046
// DefaultComboBoxModel
1047
static final class javax_swing_DefaultComboBoxModel_PersistenceDelegate extends DefaultPersistenceDelegate {
1048
protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
1049
super.initialize(type, oldInstance, newInstance, out);
1050
javax.swing.DefaultComboBoxModel<?> m = (javax.swing.DefaultComboBoxModel<?>)oldInstance;
1051
for (int i = 0; i < m.getSize(); i++) {
1052
invokeStatement(oldInstance, "addElement", new Object[]{m.getElementAt(i)}, out);
1053
}
1054
}
1055
}
1056
1057
1058
// DefaultMutableTreeNode
1059
static final class javax_swing_tree_DefaultMutableTreeNode_PersistenceDelegate extends DefaultPersistenceDelegate {
1060
protected void initialize(Class<?> type, Object oldInstance, Object
1061
newInstance, Encoder out) {
1062
super.initialize(type, oldInstance, newInstance, out);
1063
javax.swing.tree.DefaultMutableTreeNode m =
1064
(javax.swing.tree.DefaultMutableTreeNode)oldInstance;
1065
javax.swing.tree.DefaultMutableTreeNode n =
1066
(javax.swing.tree.DefaultMutableTreeNode)newInstance;
1067
for (int i = n.getChildCount(); i < m.getChildCount(); i++) {
1068
invokeStatement(oldInstance, "add", new
1069
Object[]{m.getChildAt(i)}, out);
1070
}
1071
}
1072
}
1073
1074
// ToolTipManager
1075
static final class javax_swing_ToolTipManager_PersistenceDelegate extends PersistenceDelegate {
1076
protected Expression instantiate(Object oldInstance, Encoder out) {
1077
return new Expression(oldInstance, javax.swing.ToolTipManager.class,
1078
"sharedInstance", new Object[]{});
1079
}
1080
}
1081
1082
// JTabbedPane
1083
static final class javax_swing_JTabbedPane_PersistenceDelegate extends DefaultPersistenceDelegate {
1084
protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
1085
super.initialize(type, oldInstance, newInstance, out);
1086
javax.swing.JTabbedPane p = (javax.swing.JTabbedPane)oldInstance;
1087
for (int i = 0; i < p.getTabCount(); i++) {
1088
invokeStatement(oldInstance, "addTab",
1089
new Object[]{
1090
p.getTitleAt(i),
1091
p.getIconAt(i),
1092
p.getComponentAt(i)}, out);
1093
}
1094
}
1095
}
1096
1097
// Box
1098
static final class javax_swing_Box_PersistenceDelegate extends DefaultPersistenceDelegate {
1099
protected boolean mutatesTo(Object oldInstance, Object newInstance) {
1100
return super.mutatesTo(oldInstance, newInstance) && getAxis(oldInstance).equals(getAxis(newInstance));
1101
}
1102
1103
protected Expression instantiate(Object oldInstance, Encoder out) {
1104
return new Expression(oldInstance, oldInstance.getClass(), "new", new Object[] {getAxis(oldInstance)});
1105
}
1106
1107
private Integer getAxis(Object object) {
1108
Box box = (Box) object;
1109
return (Integer) MetaData.getPrivateFieldValue(box.getLayout(), "javax.swing.BoxLayout.axis");
1110
}
1111
}
1112
1113
// JMenu
1114
// Note that we do not need to state the initialiser for
1115
// JMenuItems since the getComponents() method defined in
1116
// Container will return all of the sub menu items that
1117
// need to be added to the menu item.
1118
// Not so for JMenu apparently.
1119
static final class javax_swing_JMenu_PersistenceDelegate extends DefaultPersistenceDelegate {
1120
protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
1121
super.initialize(type, oldInstance, newInstance, out);
1122
javax.swing.JMenu m = (javax.swing.JMenu)oldInstance;
1123
java.awt.Component[] c = m.getMenuComponents();
1124
for (int i = 0; i < c.length; i++) {
1125
invokeStatement(oldInstance, "add", new Object[]{c[i]}, out);
1126
}
1127
}
1128
}
1129
1130
/**
1131
* The persistence delegate for {@link MatteBorder}.
1132
* It is impossible to use {@link DefaultPersistenceDelegate}
1133
* because this class does not have writable properties.
1134
*
1135
* @author Sergey A. Malenkov
1136
*/
1137
static final class javax_swing_border_MatteBorder_PersistenceDelegate extends PersistenceDelegate {
1138
protected Expression instantiate(Object oldInstance, Encoder out) {
1139
MatteBorder border = (MatteBorder) oldInstance;
1140
Insets insets = border.getBorderInsets();
1141
Object object = border.getTileIcon();
1142
if (object == null) {
1143
object = border.getMatteColor();
1144
}
1145
Object[] args = new Object[] {
1146
insets.top,
1147
insets.left,
1148
insets.bottom,
1149
insets.right,
1150
object,
1151
};
1152
return new Expression(border, border.getClass(), "new", args);
1153
}
1154
}
1155
1156
/* XXX - doens't seem to work. Debug later.
1157
static final class javax_swing_JMenu_PersistenceDelegate extends DefaultPersistenceDelegate {
1158
protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
1159
super.initialize(type, oldInstance, newInstance, out);
1160
javax.swing.JMenu m = (javax.swing.JMenu)oldInstance;
1161
javax.swing.JMenu n = (javax.swing.JMenu)newInstance;
1162
for (int i = n.getItemCount(); i < m.getItemCount(); i++) {
1163
invokeStatement(oldInstance, "add", new Object[]{m.getItem(i)}, out);
1164
}
1165
}
1166
}
1167
*/
1168
1169
/**
1170
* The persistence delegate for {@link PrintColorUIResource}.
1171
* It is impossible to use {@link DefaultPersistenceDelegate}
1172
* because this class has special rule for serialization:
1173
* it should be converted to {@link ColorUIResource}.
1174
*
1175
* @see PrintColorUIResource#writeReplace
1176
*
1177
* @author Sergey A. Malenkov
1178
*/
1179
static final class sun_swing_PrintColorUIResource_PersistenceDelegate extends PersistenceDelegate {
1180
protected boolean mutatesTo(Object oldInstance, Object newInstance) {
1181
return oldInstance.equals(newInstance);
1182
}
1183
1184
protected Expression instantiate(Object oldInstance, Encoder out) {
1185
Color color = (Color) oldInstance;
1186
Object[] args = new Object[] {color.getRGB()};
1187
return new Expression(color, ColorUIResource.class, "new", args);
1188
}
1189
}
1190
1191
private static final Map<String,Field> fields = Collections.synchronizedMap(new WeakHashMap<String, Field>());
1192
private static Hashtable<String, PersistenceDelegate> internalPersistenceDelegates = new Hashtable<>();
1193
1194
private static PersistenceDelegate nullPersistenceDelegate = new NullPersistenceDelegate();
1195
private static PersistenceDelegate enumPersistenceDelegate = new EnumPersistenceDelegate();
1196
private static PersistenceDelegate primitivePersistenceDelegate = new PrimitivePersistenceDelegate();
1197
private static PersistenceDelegate defaultPersistenceDelegate = new DefaultPersistenceDelegate();
1198
private static PersistenceDelegate arrayPersistenceDelegate;
1199
private static PersistenceDelegate proxyPersistenceDelegate;
1200
1201
static {
1202
1203
internalPersistenceDelegates.put("java.net.URI",
1204
new PrimitivePersistenceDelegate());
1205
1206
// it is possible because MatteBorder is assignable from MatteBorderUIResource
1207
internalPersistenceDelegates.put("javax.swing.plaf.BorderUIResource$MatteBorderUIResource",
1208
new javax_swing_border_MatteBorder_PersistenceDelegate());
1209
1210
// it is possible because FontUIResource is supported by java_awt_Font_PersistenceDelegate
1211
internalPersistenceDelegates.put("javax.swing.plaf.FontUIResource",
1212
new java_awt_Font_PersistenceDelegate());
1213
1214
// it is possible because KeyStroke is supported by java_awt_AWTKeyStroke_PersistenceDelegate
1215
internalPersistenceDelegates.put("javax.swing.KeyStroke",
1216
new java_awt_AWTKeyStroke_PersistenceDelegate());
1217
1218
internalPersistenceDelegates.put("java.sql.Date", new java_util_Date_PersistenceDelegate());
1219
internalPersistenceDelegates.put("java.sql.Time", new java_util_Date_PersistenceDelegate());
1220
}
1221
1222
@SuppressWarnings({"rawtypes", "deprecation"})
1223
public static synchronized PersistenceDelegate getPersistenceDelegate(Class type) {
1224
if (type == null) {
1225
return nullPersistenceDelegate;
1226
}
1227
if (Enum.class.isAssignableFrom(type)) {
1228
return enumPersistenceDelegate;
1229
}
1230
if (null != XMLEncoder.primitiveTypeFor(type)) {
1231
return primitivePersistenceDelegate;
1232
}
1233
// The persistence delegate for arrays is non-trivial; instantiate it lazily.
1234
if (type.isArray()) {
1235
if (arrayPersistenceDelegate == null) {
1236
arrayPersistenceDelegate = new ArrayPersistenceDelegate();
1237
}
1238
return arrayPersistenceDelegate;
1239
}
1240
// Handle proxies lazily for backward compatibility with 1.2.
1241
try {
1242
if (java.lang.reflect.Proxy.isProxyClass(type)) {
1243
if (proxyPersistenceDelegate == null) {
1244
proxyPersistenceDelegate = new ProxyPersistenceDelegate();
1245
}
1246
return proxyPersistenceDelegate;
1247
}
1248
}
1249
catch(Exception e) {}
1250
// else if (type.getDeclaringClass() != null) {
1251
// return new DefaultPersistenceDelegate(new String[]{"this$0"});
1252
// }
1253
1254
String typeName = type.getName();
1255
PersistenceDelegate pd = (PersistenceDelegate)getBeanAttribute(type, "persistenceDelegate");
1256
if (pd == null) {
1257
pd = internalPersistenceDelegates.get(typeName);
1258
if (pd != null) {
1259
return pd;
1260
}
1261
internalPersistenceDelegates.put(typeName, defaultPersistenceDelegate);
1262
try {
1263
String name = type.getName();
1264
Class<?> c = Class.forName("java.beans.MetaData$" + name.replace('.', '_')
1265
+ "_PersistenceDelegate");
1266
pd = (PersistenceDelegate)c.newInstance();
1267
internalPersistenceDelegates.put(typeName, pd);
1268
}
1269
catch (ClassNotFoundException e) {
1270
String[] properties = getConstructorProperties(type);
1271
if (properties != null) {
1272
pd = new DefaultPersistenceDelegate(properties);
1273
internalPersistenceDelegates.put(typeName, pd);
1274
}
1275
}
1276
catch (Exception e) {
1277
System.err.println("Internal error: " + e);
1278
}
1279
}
1280
1281
return (pd != null) ? pd : defaultPersistenceDelegate;
1282
}
1283
1284
private static String[] getConstructorProperties(Class<?> type) {
1285
String[] names = null;
1286
int length = 0;
1287
for (Constructor<?> constructor : type.getConstructors()) {
1288
String[] value = getAnnotationValue(constructor);
1289
if ((value != null) && (length < value.length) && isValid(constructor, value)) {
1290
names = value;
1291
length = value.length;
1292
}
1293
}
1294
return names;
1295
}
1296
1297
private static String[] getAnnotationValue(Constructor<?> constructor) {
1298
ConstructorProperties annotation = constructor.getAnnotation(ConstructorProperties.class);
1299
return (annotation != null)
1300
? annotation.value()
1301
: null;
1302
}
1303
1304
private static boolean isValid(Constructor<?> constructor, String[] names) {
1305
Class<?>[] parameters = constructor.getParameterTypes();
1306
if (names.length != parameters.length) {
1307
return false;
1308
}
1309
for (String name : names) {
1310
if (name == null) {
1311
return false;
1312
}
1313
}
1314
return true;
1315
}
1316
1317
private static Object getBeanAttribute(Class<?> type, String attribute) {
1318
try {
1319
return Introspector.getBeanInfo(type).getBeanDescriptor().getValue(attribute);
1320
} catch (IntrospectionException exception) {
1321
return null;
1322
}
1323
}
1324
1325
@SuppressWarnings("removal")
1326
static Object getPrivateFieldValue(Object instance, String name) {
1327
Field field = fields.get(name);
1328
if (field == null) {
1329
int index = name.lastIndexOf('.');
1330
final String className = name.substring(0, index);
1331
final String fieldName = name.substring(1 + index);
1332
field = AccessController.doPrivileged(new PrivilegedAction<Field>() {
1333
public Field run() {
1334
try {
1335
Field field = Class.forName(className).getDeclaredField(fieldName);
1336
field.setAccessible(true);
1337
return field;
1338
}
1339
catch (ClassNotFoundException exception) {
1340
throw new IllegalStateException("Could not find class", exception);
1341
}
1342
catch (NoSuchFieldException exception) {
1343
throw new IllegalStateException("Could not find field", exception);
1344
}
1345
}
1346
});
1347
fields.put(name, field);
1348
}
1349
try {
1350
return field.get(instance);
1351
}
1352
catch (IllegalAccessException exception) {
1353
throw new IllegalStateException("Could not get value of the field", exception);
1354
}
1355
}
1356
}
1357
1358