Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/java/beans/MetaData.java
38829 views
1
/*
2
* Copyright (c) 2000, 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
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</code>, the <code>MetaData</code> 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</CODE> 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
new Integer(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 = new Integer(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</CODE> classes.
266
* Do not extend DefaultPersistenceDelegate to improve performance and
267
* to avoid problems with <CODE>java.sql.Date</CODE>,
268
* <CODE>java.sql.Time</CODE> and <CODE>java.sql.Timestamp</CODE>.
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</CODE> 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, null);
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 static abstract 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
static final class CheckedCollection_PersistenceDelegate extends java_util_Collections {
515
protected Expression instantiate(Object oldInstance, Encoder out) {
516
Object type = MetaData.getPrivateFieldValue(oldInstance, "java.util.Collections$CheckedCollection.type");
517
List<?> list = new ArrayList<>((Collection<?>) oldInstance);
518
return new Expression(oldInstance, Collections.class, "checkedCollection", new Object[]{list, type});
519
}
520
}
521
522
static final class CheckedList_PersistenceDelegate extends java_util_Collections {
523
protected Expression instantiate(Object oldInstance, Encoder out) {
524
Object type = MetaData.getPrivateFieldValue(oldInstance, "java.util.Collections$CheckedCollection.type");
525
List<?> list = new LinkedList<>((Collection<?>) oldInstance);
526
return new Expression(oldInstance, Collections.class, "checkedList", new Object[]{list, type});
527
}
528
}
529
530
static final class CheckedRandomAccessList_PersistenceDelegate extends java_util_Collections {
531
protected Expression instantiate(Object oldInstance, Encoder out) {
532
Object type = MetaData.getPrivateFieldValue(oldInstance, "java.util.Collections$CheckedCollection.type");
533
List<?> list = new ArrayList<>((Collection<?>) oldInstance);
534
return new Expression(oldInstance, Collections.class, "checkedList", new Object[]{list, type});
535
}
536
}
537
538
static final class CheckedSet_PersistenceDelegate extends java_util_Collections {
539
protected Expression instantiate(Object oldInstance, Encoder out) {
540
Object type = MetaData.getPrivateFieldValue(oldInstance, "java.util.Collections$CheckedCollection.type");
541
Set<?> set = new HashSet<>((Set<?>) oldInstance);
542
return new Expression(oldInstance, Collections.class, "checkedSet", new Object[]{set, type});
543
}
544
}
545
546
static final class CheckedSortedSet_PersistenceDelegate extends java_util_Collections {
547
protected Expression instantiate(Object oldInstance, Encoder out) {
548
Object type = MetaData.getPrivateFieldValue(oldInstance, "java.util.Collections$CheckedCollection.type");
549
SortedSet<?> set = new TreeSet<>((SortedSet<?>) oldInstance);
550
return new Expression(oldInstance, Collections.class, "checkedSortedSet", new Object[]{set, type});
551
}
552
}
553
554
static final class CheckedMap_PersistenceDelegate extends java_util_Collections {
555
protected Expression instantiate(Object oldInstance, Encoder out) {
556
Object keyType = MetaData.getPrivateFieldValue(oldInstance, "java.util.Collections$CheckedMap.keyType");
557
Object valueType = MetaData.getPrivateFieldValue(oldInstance, "java.util.Collections$CheckedMap.valueType");
558
Map<?,?> map = new HashMap<>((Map<?,?>) oldInstance);
559
return new Expression(oldInstance, Collections.class, "checkedMap", new Object[]{map, keyType, valueType});
560
}
561
}
562
563
static final class CheckedSortedMap_PersistenceDelegate extends java_util_Collections {
564
protected Expression instantiate(Object oldInstance, Encoder out) {
565
Object keyType = MetaData.getPrivateFieldValue(oldInstance, "java.util.Collections$CheckedMap.keyType");
566
Object valueType = MetaData.getPrivateFieldValue(oldInstance, "java.util.Collections$CheckedMap.valueType");
567
SortedMap<?,?> map = new TreeMap<>((SortedMap<?,?>) oldInstance);
568
return new Expression(oldInstance, Collections.class, "checkedSortedMap", new Object[]{map, keyType, valueType});
569
}
570
}
571
}
572
573
/**
574
* The persistence delegate for <CODE>java.util.EnumMap</CODE> classes.
575
*
576
* @author Sergey A. Malenkov
577
*/
578
static final class java_util_EnumMap_PersistenceDelegate extends PersistenceDelegate {
579
protected boolean mutatesTo(Object oldInstance, Object newInstance) {
580
return super.mutatesTo(oldInstance, newInstance) && (getType(oldInstance) == getType(newInstance));
581
}
582
583
protected Expression instantiate(Object oldInstance, Encoder out) {
584
return new Expression(oldInstance, EnumMap.class, "new", new Object[] {getType(oldInstance)});
585
}
586
587
private static Object getType(Object instance) {
588
return MetaData.getPrivateFieldValue(instance, "java.util.EnumMap.keyType");
589
}
590
}
591
592
/**
593
* The persistence delegate for <CODE>java.util.EnumSet</CODE> classes.
594
*
595
* @author Sergey A. Malenkov
596
*/
597
static final class java_util_EnumSet_PersistenceDelegate extends PersistenceDelegate {
598
protected boolean mutatesTo(Object oldInstance, Object newInstance) {
599
return super.mutatesTo(oldInstance, newInstance) && (getType(oldInstance) == getType(newInstance));
600
}
601
602
protected Expression instantiate(Object oldInstance, Encoder out) {
603
return new Expression(oldInstance, EnumSet.class, "noneOf", new Object[] {getType(oldInstance)});
604
}
605
606
private static Object getType(Object instance) {
607
return MetaData.getPrivateFieldValue(instance, "java.util.EnumSet.elementType");
608
}
609
}
610
611
// Collection
612
static class java_util_Collection_PersistenceDelegate extends DefaultPersistenceDelegate {
613
protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
614
java.util.Collection<?> oldO = (java.util.Collection)oldInstance;
615
java.util.Collection<?> newO = (java.util.Collection)newInstance;
616
617
if (newO.size() != 0) {
618
invokeStatement(oldInstance, "clear", new Object[]{}, out);
619
}
620
for (Iterator<?> i = oldO.iterator(); i.hasNext();) {
621
invokeStatement(oldInstance, "add", new Object[]{i.next()}, out);
622
}
623
}
624
}
625
626
// List
627
static class java_util_List_PersistenceDelegate extends DefaultPersistenceDelegate {
628
protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
629
java.util.List<?> oldO = (java.util.List<?>)oldInstance;
630
java.util.List<?> newO = (java.util.List<?>)newInstance;
631
int oldSize = oldO.size();
632
int newSize = (newO == null) ? 0 : newO.size();
633
if (oldSize < newSize) {
634
invokeStatement(oldInstance, "clear", new Object[]{}, out);
635
newSize = 0;
636
}
637
for (int i = 0; i < newSize; i++) {
638
Object index = new Integer(i);
639
640
Expression oldGetExp = new Expression(oldInstance, "get", new Object[]{index});
641
Expression newGetExp = new Expression(newInstance, "get", new Object[]{index});
642
try {
643
Object oldValue = oldGetExp.getValue();
644
Object newValue = newGetExp.getValue();
645
out.writeExpression(oldGetExp);
646
if (!Objects.equals(newValue, out.get(oldValue))) {
647
invokeStatement(oldInstance, "set", new Object[]{index, oldValue}, out);
648
}
649
}
650
catch (Exception e) {
651
out.getExceptionListener().exceptionThrown(e);
652
}
653
}
654
for (int i = newSize; i < oldSize; i++) {
655
invokeStatement(oldInstance, "add", new Object[]{oldO.get(i)}, out);
656
}
657
}
658
}
659
660
661
// Map
662
static class java_util_Map_PersistenceDelegate extends DefaultPersistenceDelegate {
663
protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
664
// System.out.println("Initializing: " + newInstance);
665
java.util.Map<?,?> oldMap = (java.util.Map)oldInstance;
666
java.util.Map<?,?> newMap = (java.util.Map)newInstance;
667
// Remove the new elements.
668
// Do this first otherwise we undo the adding work.
669
if (newMap != null) {
670
for (Object newKey : newMap.keySet().toArray()) {
671
// PENDING: This "key" is not in the right environment.
672
if (!oldMap.containsKey(newKey)) {
673
invokeStatement(oldInstance, "remove", new Object[]{newKey}, out);
674
}
675
}
676
}
677
// Add the new elements.
678
for ( Object oldKey : oldMap.keySet() ) {
679
Expression oldGetExp = new Expression(oldInstance, "get", new Object[]{oldKey});
680
// Pending: should use newKey.
681
Expression newGetExp = new Expression(newInstance, "get", new Object[]{oldKey});
682
try {
683
Object oldValue = oldGetExp.getValue();
684
Object newValue = newGetExp.getValue();
685
out.writeExpression(oldGetExp);
686
if (!Objects.equals(newValue, out.get(oldValue))) {
687
invokeStatement(oldInstance, "put", new Object[]{oldKey, oldValue}, out);
688
} else if ((newValue == null) && !newMap.containsKey(oldKey)) {
689
// put oldValue(=null?) if oldKey is absent in newMap
690
invokeStatement(oldInstance, "put", new Object[]{oldKey, oldValue}, out);
691
}
692
}
693
catch (Exception e) {
694
out.getExceptionListener().exceptionThrown(e);
695
}
696
}
697
}
698
}
699
700
static final class java_util_AbstractCollection_PersistenceDelegate extends java_util_Collection_PersistenceDelegate {}
701
static final class java_util_AbstractList_PersistenceDelegate extends java_util_List_PersistenceDelegate {}
702
static final class java_util_AbstractMap_PersistenceDelegate extends java_util_Map_PersistenceDelegate {}
703
static final class java_util_Hashtable_PersistenceDelegate extends java_util_Map_PersistenceDelegate {}
704
705
706
// Beans
707
static final class java_beans_beancontext_BeanContextSupport_PersistenceDelegate extends java_util_Collection_PersistenceDelegate {}
708
709
// AWT
710
711
/**
712
* The persistence delegate for {@link Insets}.
713
* It is impossible to use {@link DefaultPersistenceDelegate}
714
* because this class does not have any properties.
715
*
716
* @author Sergey A. Malenkov
717
*/
718
static final class java_awt_Insets_PersistenceDelegate extends PersistenceDelegate {
719
protected boolean mutatesTo(Object oldInstance, Object newInstance) {
720
return oldInstance.equals(newInstance);
721
}
722
723
protected Expression instantiate(Object oldInstance, Encoder out) {
724
Insets insets = (Insets) oldInstance;
725
Object[] args = new Object[] {
726
insets.top,
727
insets.left,
728
insets.bottom,
729
insets.right,
730
};
731
return new Expression(insets, insets.getClass(), "new", args);
732
}
733
}
734
735
/**
736
* The persistence delegate for {@link Font}.
737
* It is impossible to use {@link DefaultPersistenceDelegate}
738
* because size of the font can be float value.
739
*
740
* @author Sergey A. Malenkov
741
*/
742
static final class java_awt_Font_PersistenceDelegate extends PersistenceDelegate {
743
protected boolean mutatesTo(Object oldInstance, Object newInstance) {
744
return oldInstance.equals(newInstance);
745
}
746
747
protected Expression instantiate(Object oldInstance, Encoder out) {
748
Font font = (Font) oldInstance;
749
750
int count = 0;
751
String family = null;
752
int style = Font.PLAIN;
753
int size = 12;
754
755
Map<TextAttribute, ?> basic = font.getAttributes();
756
Map<TextAttribute, Object> clone = new HashMap<>(basic.size());
757
for (TextAttribute key : basic.keySet()) {
758
Object value = basic.get(key);
759
if (value != null) {
760
clone.put(key, value);
761
}
762
if (key == TextAttribute.FAMILY) {
763
if (value instanceof String) {
764
count++;
765
family = (String) value;
766
}
767
}
768
else if (key == TextAttribute.WEIGHT) {
769
if (TextAttribute.WEIGHT_REGULAR.equals(value)) {
770
count++;
771
} else if (TextAttribute.WEIGHT_BOLD.equals(value)) {
772
count++;
773
style |= Font.BOLD;
774
}
775
}
776
else if (key == TextAttribute.POSTURE) {
777
if (TextAttribute.POSTURE_REGULAR.equals(value)) {
778
count++;
779
} else if (TextAttribute.POSTURE_OBLIQUE.equals(value)) {
780
count++;
781
style |= Font.ITALIC;
782
}
783
} else if (key == TextAttribute.SIZE) {
784
if (value instanceof Number) {
785
Number number = (Number) value;
786
size = number.intValue();
787
if (size == number.floatValue()) {
788
count++;
789
}
790
}
791
}
792
}
793
Class<?> type = font.getClass();
794
if (count == clone.size()) {
795
return new Expression(font, type, "new", new Object[]{family, style, size});
796
}
797
if (type == Font.class) {
798
return new Expression(font, type, "getFont", new Object[]{clone});
799
}
800
return new Expression(font, type, "new", new Object[]{Font.getFont(clone)});
801
}
802
}
803
804
/**
805
* The persistence delegate for {@link AWTKeyStroke}.
806
* It is impossible to use {@link DefaultPersistenceDelegate}
807
* because this class have no public constructor.
808
*
809
* @author Sergey A. Malenkov
810
*/
811
static final class java_awt_AWTKeyStroke_PersistenceDelegate extends PersistenceDelegate {
812
protected boolean mutatesTo(Object oldInstance, Object newInstance) {
813
return oldInstance.equals(newInstance);
814
}
815
816
protected Expression instantiate(Object oldInstance, Encoder out) {
817
AWTKeyStroke key = (AWTKeyStroke) oldInstance;
818
819
char ch = key.getKeyChar();
820
int code = key.getKeyCode();
821
int mask = key.getModifiers();
822
boolean onKeyRelease = key.isOnKeyRelease();
823
824
Object[] args = null;
825
if (ch == KeyEvent.CHAR_UNDEFINED) {
826
args = !onKeyRelease
827
? new Object[]{code, mask}
828
: new Object[]{code, mask, onKeyRelease};
829
} else if (code == KeyEvent.VK_UNDEFINED) {
830
if (!onKeyRelease) {
831
args = (mask == 0)
832
? new Object[]{ch}
833
: new Object[]{ch, mask};
834
} else if (mask == 0) {
835
args = new Object[]{ch, onKeyRelease};
836
}
837
}
838
if (args == null) {
839
throw new IllegalStateException("Unsupported KeyStroke: " + key);
840
}
841
Class<?> type = key.getClass();
842
String name = type.getName();
843
// get short name of the class
844
int index = name.lastIndexOf('.') + 1;
845
if (index > 0) {
846
name = name.substring(index);
847
}
848
return new Expression( key, type, "get" + name, args );
849
}
850
}
851
852
static class StaticFieldsPersistenceDelegate extends PersistenceDelegate {
853
protected void installFields(Encoder out, Class<?> cls) {
854
if (Modifier.isPublic(cls.getModifiers()) && isPackageAccessible(cls)) {
855
Field fields[] = cls.getFields();
856
for(int i = 0; i < fields.length; i++) {
857
Field field = fields[i];
858
// Don't install primitives, their identity will not be preserved
859
// by wrapping.
860
if (Object.class.isAssignableFrom(field.getType())) {
861
out.writeExpression(new Expression(field, "get", new Object[]{null}));
862
}
863
}
864
}
865
}
866
867
protected Expression instantiate(Object oldInstance, Encoder out) {
868
throw new RuntimeException("Unrecognized instance: " + oldInstance);
869
}
870
871
public void writeObject(Object oldInstance, Encoder out) {
872
if (out.getAttribute(this) == null) {
873
out.setAttribute(this, Boolean.TRUE);
874
installFields(out, oldInstance.getClass());
875
}
876
super.writeObject(oldInstance, out);
877
}
878
}
879
880
// SystemColor
881
static final class java_awt_SystemColor_PersistenceDelegate extends StaticFieldsPersistenceDelegate {}
882
883
// TextAttribute
884
static final class java_awt_font_TextAttribute_PersistenceDelegate extends StaticFieldsPersistenceDelegate {}
885
886
// MenuShortcut
887
static final class java_awt_MenuShortcut_PersistenceDelegate extends PersistenceDelegate {
888
protected boolean mutatesTo(Object oldInstance, Object newInstance) {
889
return oldInstance.equals(newInstance);
890
}
891
892
protected Expression instantiate(Object oldInstance, Encoder out) {
893
java.awt.MenuShortcut m = (java.awt.MenuShortcut)oldInstance;
894
return new Expression(oldInstance, m.getClass(), "new",
895
new Object[]{new Integer(m.getKey()), Boolean.valueOf(m.usesShiftModifier())});
896
}
897
}
898
899
// Component
900
static final class java_awt_Component_PersistenceDelegate extends DefaultPersistenceDelegate {
901
protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
902
super.initialize(type, oldInstance, newInstance, out);
903
java.awt.Component c = (java.awt.Component)oldInstance;
904
java.awt.Component c2 = (java.awt.Component)newInstance;
905
// The "background", "foreground" and "font" properties.
906
// The foreground and font properties of Windows change from
907
// null to defined values after the Windows are made visible -
908
// special case them for now.
909
if (!(oldInstance instanceof java.awt.Window)) {
910
Object oldBackground = c.isBackgroundSet() ? c.getBackground() : null;
911
Object newBackground = c2.isBackgroundSet() ? c2.getBackground() : null;
912
if (!Objects.equals(oldBackground, newBackground)) {
913
invokeStatement(oldInstance, "setBackground", new Object[] { oldBackground }, out);
914
}
915
Object oldForeground = c.isForegroundSet() ? c.getForeground() : null;
916
Object newForeground = c2.isForegroundSet() ? c2.getForeground() : null;
917
if (!Objects.equals(oldForeground, newForeground)) {
918
invokeStatement(oldInstance, "setForeground", new Object[] { oldForeground }, out);
919
}
920
Object oldFont = c.isFontSet() ? c.getFont() : null;
921
Object newFont = c2.isFontSet() ? c2.getFont() : null;
922
if (!Objects.equals(oldFont, newFont)) {
923
invokeStatement(oldInstance, "setFont", new Object[] { oldFont }, out);
924
}
925
}
926
927
// Bounds
928
java.awt.Container p = c.getParent();
929
if (p == null || p.getLayout() == null) {
930
// Use the most concise construct.
931
boolean locationCorrect = c.getLocation().equals(c2.getLocation());
932
boolean sizeCorrect = c.getSize().equals(c2.getSize());
933
if (!locationCorrect && !sizeCorrect) {
934
invokeStatement(oldInstance, "setBounds", new Object[]{c.getBounds()}, out);
935
}
936
else if (!locationCorrect) {
937
invokeStatement(oldInstance, "setLocation", new Object[]{c.getLocation()}, out);
938
}
939
else if (!sizeCorrect) {
940
invokeStatement(oldInstance, "setSize", new Object[]{c.getSize()}, out);
941
}
942
}
943
}
944
}
945
946
// Container
947
static final class java_awt_Container_PersistenceDelegate extends DefaultPersistenceDelegate {
948
protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
949
super.initialize(type, oldInstance, newInstance, out);
950
// Ignore the children of a JScrollPane.
951
// Pending(milne) find a better way to do this.
952
if (oldInstance instanceof javax.swing.JScrollPane) {
953
return;
954
}
955
java.awt.Container oldC = (java.awt.Container)oldInstance;
956
java.awt.Component[] oldChildren = oldC.getComponents();
957
java.awt.Container newC = (java.awt.Container)newInstance;
958
java.awt.Component[] newChildren = (newC == null) ? new java.awt.Component[0] : newC.getComponents();
959
960
BorderLayout layout = ( oldC.getLayout() instanceof BorderLayout )
961
? ( BorderLayout )oldC.getLayout()
962
: null;
963
964
JLayeredPane oldLayeredPane = (oldInstance instanceof JLayeredPane)
965
? (JLayeredPane) oldInstance
966
: null;
967
968
// Pending. Assume all the new children are unaltered.
969
for(int i = newChildren.length; i < oldChildren.length; i++) {
970
Object[] args = ( layout != null )
971
? new Object[] {oldChildren[i], layout.getConstraints( oldChildren[i] )}
972
: (oldLayeredPane != null)
973
? new Object[] {oldChildren[i], oldLayeredPane.getLayer(oldChildren[i]), Integer.valueOf(-1)}
974
: new Object[] {oldChildren[i]};
975
976
invokeStatement(oldInstance, "add", args, out);
977
}
978
}
979
}
980
981
// Choice
982
static final class java_awt_Choice_PersistenceDelegate extends DefaultPersistenceDelegate {
983
protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
984
super.initialize(type, oldInstance, newInstance, out);
985
java.awt.Choice m = (java.awt.Choice)oldInstance;
986
java.awt.Choice n = (java.awt.Choice)newInstance;
987
for (int i = n.getItemCount(); i < m.getItemCount(); i++) {
988
invokeStatement(oldInstance, "add", new Object[]{m.getItem(i)}, out);
989
}
990
}
991
}
992
993
// Menu
994
static final class java_awt_Menu_PersistenceDelegate extends DefaultPersistenceDelegate {
995
protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
996
super.initialize(type, oldInstance, newInstance, out);
997
java.awt.Menu m = (java.awt.Menu)oldInstance;
998
java.awt.Menu n = (java.awt.Menu)newInstance;
999
for (int i = n.getItemCount(); i < m.getItemCount(); i++) {
1000
invokeStatement(oldInstance, "add", new Object[]{m.getItem(i)}, out);
1001
}
1002
}
1003
}
1004
1005
// MenuBar
1006
static final class java_awt_MenuBar_PersistenceDelegate extends DefaultPersistenceDelegate {
1007
protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
1008
super.initialize(type, oldInstance, newInstance, out);
1009
java.awt.MenuBar m = (java.awt.MenuBar)oldInstance;
1010
java.awt.MenuBar n = (java.awt.MenuBar)newInstance;
1011
for (int i = n.getMenuCount(); i < m.getMenuCount(); i++) {
1012
invokeStatement(oldInstance, "add", new Object[]{m.getMenu(i)}, out);
1013
}
1014
}
1015
}
1016
1017
// List
1018
static final class java_awt_List_PersistenceDelegate extends DefaultPersistenceDelegate {
1019
protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
1020
super.initialize(type, oldInstance, newInstance, out);
1021
java.awt.List m = (java.awt.List)oldInstance;
1022
java.awt.List n = (java.awt.List)newInstance;
1023
for (int i = n.getItemCount(); i < m.getItemCount(); i++) {
1024
invokeStatement(oldInstance, "add", new Object[]{m.getItem(i)}, out);
1025
}
1026
}
1027
}
1028
1029
1030
// LayoutManagers
1031
1032
// BorderLayout
1033
static final class java_awt_BorderLayout_PersistenceDelegate extends DefaultPersistenceDelegate {
1034
private static final String[] CONSTRAINTS = {
1035
BorderLayout.NORTH,
1036
BorderLayout.SOUTH,
1037
BorderLayout.EAST,
1038
BorderLayout.WEST,
1039
BorderLayout.CENTER,
1040
BorderLayout.PAGE_START,
1041
BorderLayout.PAGE_END,
1042
BorderLayout.LINE_START,
1043
BorderLayout.LINE_END,
1044
};
1045
@Override
1046
protected void initialize(Class<?> type, Object oldInstance,
1047
Object newInstance, Encoder out) {
1048
super.initialize(type, oldInstance, newInstance, out);
1049
BorderLayout oldLayout = (BorderLayout) oldInstance;
1050
BorderLayout newLayout = (BorderLayout) newInstance;
1051
for (String constraints : CONSTRAINTS) {
1052
Object oldC = oldLayout.getLayoutComponent(constraints);
1053
Object newC = newLayout.getLayoutComponent(constraints);
1054
// Pending, assume any existing elements are OK.
1055
if (oldC != null && newC == null) {
1056
invokeStatement(oldInstance, "addLayoutComponent",
1057
new Object[] { oldC, constraints }, out);
1058
}
1059
}
1060
}
1061
}
1062
1063
// CardLayout
1064
static final class java_awt_CardLayout_PersistenceDelegate extends DefaultPersistenceDelegate {
1065
protected void initialize(Class<?> type, Object oldInstance,
1066
Object newInstance, Encoder out) {
1067
super.initialize(type, oldInstance, newInstance, out);
1068
if (getVector(newInstance).isEmpty()) {
1069
for (Object card : getVector(oldInstance)) {
1070
Object[] args = {MetaData.getPrivateFieldValue(card, "java.awt.CardLayout$Card.name"),
1071
MetaData.getPrivateFieldValue(card, "java.awt.CardLayout$Card.comp")};
1072
invokeStatement(oldInstance, "addLayoutComponent", args, out);
1073
}
1074
}
1075
}
1076
protected boolean mutatesTo(Object oldInstance, Object newInstance) {
1077
return super.mutatesTo(oldInstance, newInstance) && getVector(newInstance).isEmpty();
1078
}
1079
private static Vector<?> getVector(Object instance) {
1080
return (Vector<?>) MetaData.getPrivateFieldValue(instance, "java.awt.CardLayout.vector");
1081
}
1082
}
1083
1084
// GridBagLayout
1085
static final class java_awt_GridBagLayout_PersistenceDelegate extends DefaultPersistenceDelegate {
1086
protected void initialize(Class<?> type, Object oldInstance,
1087
Object newInstance, Encoder out) {
1088
super.initialize(type, oldInstance, newInstance, out);
1089
if (getHashtable(newInstance).isEmpty()) {
1090
for (Map.Entry<?,?> entry : getHashtable(oldInstance).entrySet()) {
1091
Object[] args = {entry.getKey(), entry.getValue()};
1092
invokeStatement(oldInstance, "addLayoutComponent", args, out);
1093
}
1094
}
1095
}
1096
protected boolean mutatesTo(Object oldInstance, Object newInstance) {
1097
return super.mutatesTo(oldInstance, newInstance) && getHashtable(newInstance).isEmpty();
1098
}
1099
private static Hashtable<?,?> getHashtable(Object instance) {
1100
return (Hashtable<?,?>) MetaData.getPrivateFieldValue(instance, "java.awt.GridBagLayout.comptable");
1101
}
1102
}
1103
1104
// Swing
1105
1106
// JFrame (If we do this for Window instead of JFrame, the setVisible call
1107
// will be issued before we have added all the children to the JFrame and
1108
// will appear blank).
1109
static final class javax_swing_JFrame_PersistenceDelegate extends DefaultPersistenceDelegate {
1110
protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
1111
super.initialize(type, oldInstance, newInstance, out);
1112
java.awt.Window oldC = (java.awt.Window)oldInstance;
1113
java.awt.Window newC = (java.awt.Window)newInstance;
1114
boolean oldV = oldC.isVisible();
1115
boolean newV = newC.isVisible();
1116
if (newV != oldV) {
1117
// false means: don't execute this statement at write time.
1118
boolean executeStatements = out.executeStatements;
1119
out.executeStatements = false;
1120
invokeStatement(oldInstance, "setVisible", new Object[]{Boolean.valueOf(oldV)}, out);
1121
out.executeStatements = executeStatements;
1122
}
1123
}
1124
}
1125
1126
// Models
1127
1128
// DefaultListModel
1129
static final class javax_swing_DefaultListModel_PersistenceDelegate extends DefaultPersistenceDelegate {
1130
protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
1131
// Note, the "size" property will be set here.
1132
super.initialize(type, oldInstance, newInstance, out);
1133
javax.swing.DefaultListModel<?> m = (javax.swing.DefaultListModel<?>)oldInstance;
1134
javax.swing.DefaultListModel<?> n = (javax.swing.DefaultListModel<?>)newInstance;
1135
for (int i = n.getSize(); i < m.getSize(); i++) {
1136
invokeStatement(oldInstance, "add", // Can also use "addElement".
1137
new Object[]{m.getElementAt(i)}, out);
1138
}
1139
}
1140
}
1141
1142
// DefaultComboBoxModel
1143
static final class javax_swing_DefaultComboBoxModel_PersistenceDelegate extends DefaultPersistenceDelegate {
1144
protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
1145
super.initialize(type, oldInstance, newInstance, out);
1146
javax.swing.DefaultComboBoxModel<?> m = (javax.swing.DefaultComboBoxModel<?>)oldInstance;
1147
for (int i = 0; i < m.getSize(); i++) {
1148
invokeStatement(oldInstance, "addElement", new Object[]{m.getElementAt(i)}, out);
1149
}
1150
}
1151
}
1152
1153
1154
// DefaultMutableTreeNode
1155
static final class javax_swing_tree_DefaultMutableTreeNode_PersistenceDelegate extends DefaultPersistenceDelegate {
1156
protected void initialize(Class<?> type, Object oldInstance, Object
1157
newInstance, Encoder out) {
1158
super.initialize(type, oldInstance, newInstance, out);
1159
javax.swing.tree.DefaultMutableTreeNode m =
1160
(javax.swing.tree.DefaultMutableTreeNode)oldInstance;
1161
javax.swing.tree.DefaultMutableTreeNode n =
1162
(javax.swing.tree.DefaultMutableTreeNode)newInstance;
1163
for (int i = n.getChildCount(); i < m.getChildCount(); i++) {
1164
invokeStatement(oldInstance, "add", new
1165
Object[]{m.getChildAt(i)}, out);
1166
}
1167
}
1168
}
1169
1170
// ToolTipManager
1171
static final class javax_swing_ToolTipManager_PersistenceDelegate extends PersistenceDelegate {
1172
protected Expression instantiate(Object oldInstance, Encoder out) {
1173
return new Expression(oldInstance, javax.swing.ToolTipManager.class,
1174
"sharedInstance", new Object[]{});
1175
}
1176
}
1177
1178
// JTabbedPane
1179
static final class javax_swing_JTabbedPane_PersistenceDelegate extends DefaultPersistenceDelegate {
1180
protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
1181
super.initialize(type, oldInstance, newInstance, out);
1182
javax.swing.JTabbedPane p = (javax.swing.JTabbedPane)oldInstance;
1183
for (int i = 0; i < p.getTabCount(); i++) {
1184
invokeStatement(oldInstance, "addTab",
1185
new Object[]{
1186
p.getTitleAt(i),
1187
p.getIconAt(i),
1188
p.getComponentAt(i)}, out);
1189
}
1190
}
1191
}
1192
1193
// Box
1194
static final class javax_swing_Box_PersistenceDelegate extends DefaultPersistenceDelegate {
1195
protected boolean mutatesTo(Object oldInstance, Object newInstance) {
1196
return super.mutatesTo(oldInstance, newInstance) && getAxis(oldInstance).equals(getAxis(newInstance));
1197
}
1198
1199
protected Expression instantiate(Object oldInstance, Encoder out) {
1200
return new Expression(oldInstance, oldInstance.getClass(), "new", new Object[] {getAxis(oldInstance)});
1201
}
1202
1203
private Integer getAxis(Object object) {
1204
Box box = (Box) object;
1205
return (Integer) MetaData.getPrivateFieldValue(box.getLayout(), "javax.swing.BoxLayout.axis");
1206
}
1207
}
1208
1209
// JMenu
1210
// Note that we do not need to state the initialiser for
1211
// JMenuItems since the getComponents() method defined in
1212
// Container will return all of the sub menu items that
1213
// need to be added to the menu item.
1214
// Not so for JMenu apparently.
1215
static final class javax_swing_JMenu_PersistenceDelegate extends DefaultPersistenceDelegate {
1216
protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
1217
super.initialize(type, oldInstance, newInstance, out);
1218
javax.swing.JMenu m = (javax.swing.JMenu)oldInstance;
1219
java.awt.Component[] c = m.getMenuComponents();
1220
for (int i = 0; i < c.length; i++) {
1221
invokeStatement(oldInstance, "add", new Object[]{c[i]}, out);
1222
}
1223
}
1224
}
1225
1226
/**
1227
* The persistence delegate for {@link MatteBorder}.
1228
* It is impossible to use {@link DefaultPersistenceDelegate}
1229
* because this class does not have writable properties.
1230
*
1231
* @author Sergey A. Malenkov
1232
*/
1233
static final class javax_swing_border_MatteBorder_PersistenceDelegate extends PersistenceDelegate {
1234
protected Expression instantiate(Object oldInstance, Encoder out) {
1235
MatteBorder border = (MatteBorder) oldInstance;
1236
Insets insets = border.getBorderInsets();
1237
Object object = border.getTileIcon();
1238
if (object == null) {
1239
object = border.getMatteColor();
1240
}
1241
Object[] args = new Object[] {
1242
insets.top,
1243
insets.left,
1244
insets.bottom,
1245
insets.right,
1246
object,
1247
};
1248
return new Expression(border, border.getClass(), "new", args);
1249
}
1250
}
1251
1252
/* XXX - doens't seem to work. Debug later.
1253
static final class javax_swing_JMenu_PersistenceDelegate extends DefaultPersistenceDelegate {
1254
protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
1255
super.initialize(type, oldInstance, newInstance, out);
1256
javax.swing.JMenu m = (javax.swing.JMenu)oldInstance;
1257
javax.swing.JMenu n = (javax.swing.JMenu)newInstance;
1258
for (int i = n.getItemCount(); i < m.getItemCount(); i++) {
1259
invokeStatement(oldInstance, "add", new Object[]{m.getItem(i)}, out);
1260
}
1261
}
1262
}
1263
*/
1264
1265
/**
1266
* The persistence delegate for {@link PrintColorUIResource}.
1267
* It is impossible to use {@link DefaultPersistenceDelegate}
1268
* because this class has special rule for serialization:
1269
* it should be converted to {@link ColorUIResource}.
1270
*
1271
* @see PrintColorUIResource#writeReplace
1272
*
1273
* @author Sergey A. Malenkov
1274
*/
1275
static final class sun_swing_PrintColorUIResource_PersistenceDelegate extends PersistenceDelegate {
1276
protected boolean mutatesTo(Object oldInstance, Object newInstance) {
1277
return oldInstance.equals(newInstance);
1278
}
1279
1280
protected Expression instantiate(Object oldInstance, Encoder out) {
1281
Color color = (Color) oldInstance;
1282
Object[] args = new Object[] {color.getRGB()};
1283
return new Expression(color, ColorUIResource.class, "new", args);
1284
}
1285
}
1286
1287
private static final Map<String,Field> fields = Collections.synchronizedMap(new WeakHashMap<String, Field>());
1288
private static Hashtable<String, PersistenceDelegate> internalPersistenceDelegates = new Hashtable<>();
1289
1290
private static PersistenceDelegate nullPersistenceDelegate = new NullPersistenceDelegate();
1291
private static PersistenceDelegate enumPersistenceDelegate = new EnumPersistenceDelegate();
1292
private static PersistenceDelegate primitivePersistenceDelegate = new PrimitivePersistenceDelegate();
1293
private static PersistenceDelegate defaultPersistenceDelegate = new DefaultPersistenceDelegate();
1294
private static PersistenceDelegate arrayPersistenceDelegate;
1295
private static PersistenceDelegate proxyPersistenceDelegate;
1296
1297
static {
1298
1299
internalPersistenceDelegates.put("java.net.URI",
1300
new PrimitivePersistenceDelegate());
1301
1302
// it is possible because MatteBorder is assignable from MatteBorderUIResource
1303
internalPersistenceDelegates.put("javax.swing.plaf.BorderUIResource$MatteBorderUIResource",
1304
new javax_swing_border_MatteBorder_PersistenceDelegate());
1305
1306
// it is possible because FontUIResource is supported by java_awt_Font_PersistenceDelegate
1307
internalPersistenceDelegates.put("javax.swing.plaf.FontUIResource",
1308
new java_awt_Font_PersistenceDelegate());
1309
1310
// it is possible because KeyStroke is supported by java_awt_AWTKeyStroke_PersistenceDelegate
1311
internalPersistenceDelegates.put("javax.swing.KeyStroke",
1312
new java_awt_AWTKeyStroke_PersistenceDelegate());
1313
1314
internalPersistenceDelegates.put("java.sql.Date", new java_util_Date_PersistenceDelegate());
1315
internalPersistenceDelegates.put("java.sql.Time", new java_util_Date_PersistenceDelegate());
1316
1317
internalPersistenceDelegates.put("java.util.JumboEnumSet", new java_util_EnumSet_PersistenceDelegate());
1318
internalPersistenceDelegates.put("java.util.RegularEnumSet", new java_util_EnumSet_PersistenceDelegate());
1319
}
1320
1321
@SuppressWarnings("rawtypes")
1322
public synchronized static PersistenceDelegate getPersistenceDelegate(Class type) {
1323
if (type == null) {
1324
return nullPersistenceDelegate;
1325
}
1326
if (Enum.class.isAssignableFrom(type)) {
1327
return enumPersistenceDelegate;
1328
}
1329
if (null != XMLEncoder.primitiveTypeFor(type)) {
1330
return primitivePersistenceDelegate;
1331
}
1332
// The persistence delegate for arrays is non-trivial; instantiate it lazily.
1333
if (type.isArray()) {
1334
if (arrayPersistenceDelegate == null) {
1335
arrayPersistenceDelegate = new ArrayPersistenceDelegate();
1336
}
1337
return arrayPersistenceDelegate;
1338
}
1339
// Handle proxies lazily for backward compatibility with 1.2.
1340
try {
1341
if (java.lang.reflect.Proxy.isProxyClass(type)) {
1342
if (proxyPersistenceDelegate == null) {
1343
proxyPersistenceDelegate = new ProxyPersistenceDelegate();
1344
}
1345
return proxyPersistenceDelegate;
1346
}
1347
}
1348
catch(Exception e) {}
1349
// else if (type.getDeclaringClass() != null) {
1350
// return new DefaultPersistenceDelegate(new String[]{"this$0"});
1351
// }
1352
1353
String typeName = type.getName();
1354
PersistenceDelegate pd = (PersistenceDelegate)getBeanAttribute(type, "persistenceDelegate");
1355
if (pd == null) {
1356
pd = internalPersistenceDelegates.get(typeName);
1357
if (pd != null) {
1358
return pd;
1359
}
1360
internalPersistenceDelegates.put(typeName, defaultPersistenceDelegate);
1361
try {
1362
String name = type.getName();
1363
Class c = Class.forName("java.beans.MetaData$" + name.replace('.', '_')
1364
+ "_PersistenceDelegate");
1365
pd = (PersistenceDelegate)c.newInstance();
1366
internalPersistenceDelegates.put(typeName, pd);
1367
}
1368
catch (ClassNotFoundException e) {
1369
String[] properties = getConstructorProperties(type);
1370
if (properties != null) {
1371
pd = new DefaultPersistenceDelegate(properties);
1372
internalPersistenceDelegates.put(typeName, pd);
1373
}
1374
}
1375
catch (Exception e) {
1376
System.err.println("Internal error: " + e);
1377
}
1378
}
1379
1380
return (pd != null) ? pd : defaultPersistenceDelegate;
1381
}
1382
1383
private static String[] getConstructorProperties(Class<?> type) {
1384
String[] names = null;
1385
int length = 0;
1386
for (Constructor<?> constructor : type.getConstructors()) {
1387
String[] value = getAnnotationValue(constructor);
1388
if ((value != null) && (length < value.length) && isValid(constructor, value)) {
1389
names = value;
1390
length = value.length;
1391
}
1392
}
1393
return names;
1394
}
1395
1396
private static String[] getAnnotationValue(Constructor<?> constructor) {
1397
ConstructorProperties annotation = constructor.getAnnotation(ConstructorProperties.class);
1398
return (annotation != null)
1399
? annotation.value()
1400
: null;
1401
}
1402
1403
private static boolean isValid(Constructor<?> constructor, String[] names) {
1404
Class[] parameters = constructor.getParameterTypes();
1405
if (names.length != parameters.length) {
1406
return false;
1407
}
1408
for (String name : names) {
1409
if (name == null) {
1410
return false;
1411
}
1412
}
1413
return true;
1414
}
1415
1416
private static Object getBeanAttribute(Class<?> type, String attribute) {
1417
try {
1418
return Introspector.getBeanInfo(type).getBeanDescriptor().getValue(attribute);
1419
} catch (IntrospectionException exception) {
1420
return null;
1421
}
1422
}
1423
1424
static Object getPrivateFieldValue(Object instance, String name) {
1425
Field field = fields.get(name);
1426
if (field == null) {
1427
int index = name.lastIndexOf('.');
1428
final String className = name.substring(0, index);
1429
final String fieldName = name.substring(1 + index);
1430
field = AccessController.doPrivileged(new PrivilegedAction<Field>() {
1431
public Field run() {
1432
try {
1433
Field field = Class.forName(className).getDeclaredField(fieldName);
1434
field.setAccessible(true);
1435
return field;
1436
}
1437
catch (ClassNotFoundException exception) {
1438
throw new IllegalStateException("Could not find class", exception);
1439
}
1440
catch (NoSuchFieldException exception) {
1441
throw new IllegalStateException("Could not find field", exception);
1442
}
1443
}
1444
});
1445
fields.put(name, field);
1446
}
1447
try {
1448
return field.get(instance);
1449
}
1450
catch (IllegalAccessException exception) {
1451
throw new IllegalStateException("Could not get value of the field", exception);
1452
}
1453
}
1454
}
1455
1456