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.InvocationTargetException;
46
47 import java.security.AccessController;
48 import java.security.PrivilegedAction;
49
50 import java.util.*;
51
52 import javax.swing.Box;
53 import javax.swing.JLayeredPane;
54 import javax.swing.border.MatteBorder;
55 import javax.swing.plaf.ColorUIResource;
56
57 import sun.swing.PrintColorUIResource;
58
59 /*
60 * Like the <code>Intropector</code>, the <code>MetaData</code> class
61 * contains <em>meta</em> objects that describe the way
62 * classes should express their state in terms of their
63 * own public APIs.
64 *
65 * @see java.beans.Intropector
66 *
67 * @author Philip Milne
68 * @author Steve Langley
69 */
70
71 class NullPersistenceDelegate extends PersistenceDelegate {
72 // Note this will be called by all classes when they reach the
73 // top of their superclass chain.
74 protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
75 }
76 protected Expression instantiate(Object oldInstance, Encoder out) { return null; }
77
78 public void writeObject(Object oldInstance, Encoder out) {
117 protected Expression instantiate(Object oldInstance, Encoder out) {
118 // System.out.println("instantiate: " + type + " " + oldInstance);
119 Class oldClass = oldInstance.getClass();
120 return new Expression(oldInstance, Array.class, "newInstance",
121 new Object[]{oldClass.getComponentType(),
122 new Integer(Array.getLength(oldInstance))});
123 }
124
125 protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
126 int n = Array.getLength(oldInstance);
127 for (int i = 0; i < n; i++) {
128 Object index = new Integer(i);
129 // Expression oldGetExp = new Expression(Array.class, "get", new Object[]{oldInstance, index});
130 // Expression newGetExp = new Expression(Array.class, "get", new Object[]{newInstance, index});
131 Expression oldGetExp = new Expression(oldInstance, "get", new Object[]{index});
132 Expression newGetExp = new Expression(newInstance, "get", new Object[]{index});
133 try {
134 Object oldValue = oldGetExp.getValue();
135 Object newValue = newGetExp.getValue();
136 out.writeExpression(oldGetExp);
137 if (!MetaData.equals(newValue, out.get(oldValue))) {
138 // System.out.println("Not equal: " + newGetExp + " != " + actualGetExp);
139 // invokeStatement(Array.class, "set", new Object[]{oldInstance, index, oldValue}, out);
140 DefaultPersistenceDelegate.invokeStatement(oldInstance, "set", new Object[]{index, oldValue}, out);
141 }
142 }
143 catch (Exception e) {
144 // System.err.println("Warning:: failed to write: " + oldGetExp);
145 out.getExceptionListener().exceptionThrown(e);
146 }
147 }
148 }
149 }
150
151 class ProxyPersistenceDelegate extends PersistenceDelegate {
152 protected Expression instantiate(Object oldInstance, Encoder out) {
153 Class type = oldInstance.getClass();
154 java.lang.reflect.Proxy p = (java.lang.reflect.Proxy)oldInstance;
155 // This unappealing hack is not required but makes the
156 // representation of EventHandlers much more concise.
157 java.lang.reflect.InvocationHandler ih = java.lang.reflect.Proxy.getInvocationHandler(p);
618 // List
619 class java_util_List_PersistenceDelegate extends DefaultPersistenceDelegate {
620 protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
621 java.util.List oldO = (java.util.List)oldInstance;
622 java.util.List newO = (java.util.List)newInstance;
623 int oldSize = oldO.size();
624 int newSize = (newO == null) ? 0 : newO.size();
625 if (oldSize < newSize) {
626 invokeStatement(oldInstance, "clear", new Object[]{}, out);
627 newSize = 0;
628 }
629 for (int i = 0; i < newSize; i++) {
630 Object index = new Integer(i);
631
632 Expression oldGetExp = new Expression(oldInstance, "get", new Object[]{index});
633 Expression newGetExp = new Expression(newInstance, "get", new Object[]{index});
634 try {
635 Object oldValue = oldGetExp.getValue();
636 Object newValue = newGetExp.getValue();
637 out.writeExpression(oldGetExp);
638 if (!MetaData.equals(newValue, out.get(oldValue))) {
639 invokeStatement(oldInstance, "set", new Object[]{index, oldValue}, out);
640 }
641 }
642 catch (Exception e) {
643 out.getExceptionListener().exceptionThrown(e);
644 }
645 }
646 for (int i = newSize; i < oldSize; i++) {
647 invokeStatement(oldInstance, "add", new Object[]{oldO.get(i)}, out);
648 }
649 }
650 }
651
652
653 // Map
654 class java_util_Map_PersistenceDelegate extends DefaultPersistenceDelegate {
655 protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
656 // System.out.println("Initializing: " + newInstance);
657 java.util.Map oldMap = (java.util.Map)oldInstance;
658 java.util.Map newMap = (java.util.Map)newInstance;
659 // Remove the new elements.
660 // Do this first otherwise we undo the adding work.
661 if (newMap != null) {
662 for (Object newKey : newMap.keySet().toArray()) {
663 // PENDING: This "key" is not in the right environment.
664 if (!oldMap.containsKey(newKey)) {
665 invokeStatement(oldInstance, "remove", new Object[]{newKey}, out);
666 }
667 }
668 }
669 // Add the new elements.
670 for ( Object oldKey : oldMap.keySet() ) {
671 Expression oldGetExp = new Expression(oldInstance, "get", new Object[]{oldKey});
672 // Pending: should use newKey.
673 Expression newGetExp = new Expression(newInstance, "get", new Object[]{oldKey});
674 try {
675 Object oldValue = oldGetExp.getValue();
676 Object newValue = newGetExp.getValue();
677 out.writeExpression(oldGetExp);
678 if (!MetaData.equals(newValue, out.get(oldValue))) {
679 invokeStatement(oldInstance, "put", new Object[]{oldKey, oldValue}, out);
680 } else if ((newValue == null) && !newMap.containsKey(oldKey)) {
681 // put oldValue(=null?) if oldKey is absent in newMap
682 invokeStatement(oldInstance, "put", new Object[]{oldKey, oldValue}, out);
683 }
684 }
685 catch (Exception e) {
686 out.getExceptionListener().exceptionThrown(e);
687 }
688 }
689 }
690 }
691
692 class java_util_AbstractCollection_PersistenceDelegate extends java_util_Collection_PersistenceDelegate {}
693 class java_util_AbstractList_PersistenceDelegate extends java_util_List_PersistenceDelegate {}
694 class java_util_AbstractMap_PersistenceDelegate extends java_util_Map_PersistenceDelegate {}
695 class java_util_Hashtable_PersistenceDelegate extends java_util_Map_PersistenceDelegate {}
696
697
698 // Beans
882 protected Expression instantiate(Object oldInstance, Encoder out) {
883 java.awt.MenuShortcut m = (java.awt.MenuShortcut)oldInstance;
884 return new Expression(oldInstance, m.getClass(), "new",
885 new Object[]{new Integer(m.getKey()), Boolean.valueOf(m.usesShiftModifier())});
886 }
887 }
888
889 // Component
890 class java_awt_Component_PersistenceDelegate extends DefaultPersistenceDelegate {
891 protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
892 super.initialize(type, oldInstance, newInstance, out);
893 java.awt.Component c = (java.awt.Component)oldInstance;
894 java.awt.Component c2 = (java.awt.Component)newInstance;
895 // The "background", "foreground" and "font" properties.
896 // The foreground and font properties of Windows change from
897 // null to defined values after the Windows are made visible -
898 // special case them for now.
899 if (!(oldInstance instanceof java.awt.Window)) {
900 Object oldBackground = c.isBackgroundSet() ? c.getBackground() : null;
901 Object newBackground = c2.isBackgroundSet() ? c2.getBackground() : null;
902 if (!MetaData.equals(oldBackground, newBackground)) {
903 invokeStatement(oldInstance, "setBackground", new Object[] { oldBackground }, out);
904 }
905 Object oldForeground = c.isForegroundSet() ? c.getForeground() : null;
906 Object newForeground = c2.isForegroundSet() ? c2.getForeground() : null;
907 if (!MetaData.equals(oldForeground, newForeground)) {
908 invokeStatement(oldInstance, "setForeground", new Object[] { oldForeground }, out);
909 }
910 Object oldFont = c.isFontSet() ? c.getFont() : null;
911 Object newFont = c2.isFontSet() ? c2.getFont() : null;
912 if (!MetaData.equals(oldFont, newFont)) {
913 invokeStatement(oldInstance, "setFont", new Object[] { oldFont }, out);
914 }
915 }
916
917 // Bounds
918 java.awt.Container p = c.getParent();
919 if (p == null || p.getLayout() == null) {
920 // Use the most concise construct.
921 boolean locationCorrect = c.getLocation().equals(c2.getLocation());
922 boolean sizeCorrect = c.getSize().equals(c2.getSize());
923 if (!locationCorrect && !sizeCorrect) {
924 invokeStatement(oldInstance, "setBounds", new Object[]{c.getBounds()}, out);
925 }
926 else if (!locationCorrect) {
927 invokeStatement(oldInstance, "setLocation", new Object[]{c.getLocation()}, out);
928 }
929 else if (!sizeCorrect) {
930 invokeStatement(oldInstance, "setSize", new Object[]{c.getSize()}, out);
931 }
932 }
1289
1290 // it is possible because MatteBorder is assignable from MatteBorderUIResource
1291 internalPersistenceDelegates.put("javax.swing.plaf.BorderUIResource$MatteBorderUIResource",
1292 new javax_swing_border_MatteBorder_PersistenceDelegate());
1293
1294 // it is possible because FontUIResource is supported by java_awt_Font_PersistenceDelegate
1295 internalPersistenceDelegates.put("javax.swing.plaf.FontUIResource",
1296 new java_awt_Font_PersistenceDelegate());
1297
1298 // it is possible because KeyStroke is supported by java_awt_AWTKeyStroke_PersistenceDelegate
1299 internalPersistenceDelegates.put("javax.swing.KeyStroke",
1300 new java_awt_AWTKeyStroke_PersistenceDelegate());
1301
1302 internalPersistenceDelegates.put("java.sql.Date", new java_util_Date_PersistenceDelegate());
1303 internalPersistenceDelegates.put("java.sql.Time", new java_util_Date_PersistenceDelegate());
1304
1305 internalPersistenceDelegates.put("java.util.JumboEnumSet", new java_util_EnumSet_PersistenceDelegate());
1306 internalPersistenceDelegates.put("java.util.RegularEnumSet", new java_util_EnumSet_PersistenceDelegate());
1307 }
1308
1309 /*pp*/ static boolean equals(Object o1, Object o2) {
1310 return (o1 == null) ? (o2 == null) : o1.equals(o2);
1311 }
1312
1313 public synchronized static PersistenceDelegate getPersistenceDelegate(Class type) {
1314 if (type == null) {
1315 return nullPersistenceDelegate;
1316 }
1317 if (Enum.class.isAssignableFrom(type)) {
1318 return enumPersistenceDelegate;
1319 }
1320 if (ReflectionUtils.isPrimitive(type)) {
1321 return primitivePersistenceDelegate;
1322 }
1323 // The persistence delegate for arrays is non-trivial; instantiate it lazily.
1324 if (type.isArray()) {
1325 if (arrayPersistenceDelegate == null) {
1326 arrayPersistenceDelegate = new ArrayPersistenceDelegate();
1327 }
1328 return arrayPersistenceDelegate;
1329 }
1330 // Handle proxies lazily for backward compatibility with 1.2.
1331 try {
1332 if (java.lang.reflect.Proxy.isProxyClass(type)) {
|
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.InvocationTargetException;
46
47 import java.security.AccessController;
48 import java.security.PrivilegedAction;
49
50 import java.util.*;
51
52 import javax.swing.Box;
53 import javax.swing.JLayeredPane;
54 import javax.swing.border.MatteBorder;
55 import javax.swing.plaf.ColorUIResource;
56
57 import sun.swing.PrintColorUIResource;
58
59 import java.util.Objects;
60
61 /*
62 * Like the <code>Intropector</code>, the <code>MetaData</code> class
63 * contains <em>meta</em> objects that describe the way
64 * classes should express their state in terms of their
65 * own public APIs.
66 *
67 * @see java.beans.Intropector
68 *
69 * @author Philip Milne
70 * @author Steve Langley
71 */
72
73 class NullPersistenceDelegate extends PersistenceDelegate {
74 // Note this will be called by all classes when they reach the
75 // top of their superclass chain.
76 protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
77 }
78 protected Expression instantiate(Object oldInstance, Encoder out) { return null; }
79
80 public void writeObject(Object oldInstance, Encoder out) {
119 protected Expression instantiate(Object oldInstance, Encoder out) {
120 // System.out.println("instantiate: " + type + " " + oldInstance);
121 Class oldClass = oldInstance.getClass();
122 return new Expression(oldInstance, Array.class, "newInstance",
123 new Object[]{oldClass.getComponentType(),
124 new Integer(Array.getLength(oldInstance))});
125 }
126
127 protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
128 int n = Array.getLength(oldInstance);
129 for (int i = 0; i < n; i++) {
130 Object index = new Integer(i);
131 // Expression oldGetExp = new Expression(Array.class, "get", new Object[]{oldInstance, index});
132 // Expression newGetExp = new Expression(Array.class, "get", new Object[]{newInstance, index});
133 Expression oldGetExp = new Expression(oldInstance, "get", new Object[]{index});
134 Expression newGetExp = new Expression(newInstance, "get", new Object[]{index});
135 try {
136 Object oldValue = oldGetExp.getValue();
137 Object newValue = newGetExp.getValue();
138 out.writeExpression(oldGetExp);
139 if (!Objects.equals(newValue, out.get(oldValue))) {
140 // System.out.println("Not equal: " + newGetExp + " != " + actualGetExp);
141 // invokeStatement(Array.class, "set", new Object[]{oldInstance, index, oldValue}, out);
142 DefaultPersistenceDelegate.invokeStatement(oldInstance, "set", new Object[]{index, oldValue}, out);
143 }
144 }
145 catch (Exception e) {
146 // System.err.println("Warning:: failed to write: " + oldGetExp);
147 out.getExceptionListener().exceptionThrown(e);
148 }
149 }
150 }
151 }
152
153 class ProxyPersistenceDelegate extends PersistenceDelegate {
154 protected Expression instantiate(Object oldInstance, Encoder out) {
155 Class type = oldInstance.getClass();
156 java.lang.reflect.Proxy p = (java.lang.reflect.Proxy)oldInstance;
157 // This unappealing hack is not required but makes the
158 // representation of EventHandlers much more concise.
159 java.lang.reflect.InvocationHandler ih = java.lang.reflect.Proxy.getInvocationHandler(p);
620 // List
621 class java_util_List_PersistenceDelegate extends DefaultPersistenceDelegate {
622 protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
623 java.util.List oldO = (java.util.List)oldInstance;
624 java.util.List newO = (java.util.List)newInstance;
625 int oldSize = oldO.size();
626 int newSize = (newO == null) ? 0 : newO.size();
627 if (oldSize < newSize) {
628 invokeStatement(oldInstance, "clear", new Object[]{}, out);
629 newSize = 0;
630 }
631 for (int i = 0; i < newSize; i++) {
632 Object index = new Integer(i);
633
634 Expression oldGetExp = new Expression(oldInstance, "get", new Object[]{index});
635 Expression newGetExp = new Expression(newInstance, "get", new Object[]{index});
636 try {
637 Object oldValue = oldGetExp.getValue();
638 Object newValue = newGetExp.getValue();
639 out.writeExpression(oldGetExp);
640 if (!Objects.equals(newValue, out.get(oldValue))) {
641 invokeStatement(oldInstance, "set", new Object[]{index, oldValue}, out);
642 }
643 }
644 catch (Exception e) {
645 out.getExceptionListener().exceptionThrown(e);
646 }
647 }
648 for (int i = newSize; i < oldSize; i++) {
649 invokeStatement(oldInstance, "add", new Object[]{oldO.get(i)}, out);
650 }
651 }
652 }
653
654
655 // Map
656 class java_util_Map_PersistenceDelegate extends DefaultPersistenceDelegate {
657 protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
658 // System.out.println("Initializing: " + newInstance);
659 java.util.Map oldMap = (java.util.Map)oldInstance;
660 java.util.Map newMap = (java.util.Map)newInstance;
661 // Remove the new elements.
662 // Do this first otherwise we undo the adding work.
663 if (newMap != null) {
664 for (Object newKey : newMap.keySet().toArray()) {
665 // PENDING: This "key" is not in the right environment.
666 if (!oldMap.containsKey(newKey)) {
667 invokeStatement(oldInstance, "remove", new Object[]{newKey}, out);
668 }
669 }
670 }
671 // Add the new elements.
672 for ( Object oldKey : oldMap.keySet() ) {
673 Expression oldGetExp = new Expression(oldInstance, "get", new Object[]{oldKey});
674 // Pending: should use newKey.
675 Expression newGetExp = new Expression(newInstance, "get", new Object[]{oldKey});
676 try {
677 Object oldValue = oldGetExp.getValue();
678 Object newValue = newGetExp.getValue();
679 out.writeExpression(oldGetExp);
680 if (!Objects.equals(newValue, out.get(oldValue))) {
681 invokeStatement(oldInstance, "put", new Object[]{oldKey, oldValue}, out);
682 } else if ((newValue == null) && !newMap.containsKey(oldKey)) {
683 // put oldValue(=null?) if oldKey is absent in newMap
684 invokeStatement(oldInstance, "put", new Object[]{oldKey, oldValue}, out);
685 }
686 }
687 catch (Exception e) {
688 out.getExceptionListener().exceptionThrown(e);
689 }
690 }
691 }
692 }
693
694 class java_util_AbstractCollection_PersistenceDelegate extends java_util_Collection_PersistenceDelegate {}
695 class java_util_AbstractList_PersistenceDelegate extends java_util_List_PersistenceDelegate {}
696 class java_util_AbstractMap_PersistenceDelegate extends java_util_Map_PersistenceDelegate {}
697 class java_util_Hashtable_PersistenceDelegate extends java_util_Map_PersistenceDelegate {}
698
699
700 // Beans
884 protected Expression instantiate(Object oldInstance, Encoder out) {
885 java.awt.MenuShortcut m = (java.awt.MenuShortcut)oldInstance;
886 return new Expression(oldInstance, m.getClass(), "new",
887 new Object[]{new Integer(m.getKey()), Boolean.valueOf(m.usesShiftModifier())});
888 }
889 }
890
891 // Component
892 class java_awt_Component_PersistenceDelegate extends DefaultPersistenceDelegate {
893 protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
894 super.initialize(type, oldInstance, newInstance, out);
895 java.awt.Component c = (java.awt.Component)oldInstance;
896 java.awt.Component c2 = (java.awt.Component)newInstance;
897 // The "background", "foreground" and "font" properties.
898 // The foreground and font properties of Windows change from
899 // null to defined values after the Windows are made visible -
900 // special case them for now.
901 if (!(oldInstance instanceof java.awt.Window)) {
902 Object oldBackground = c.isBackgroundSet() ? c.getBackground() : null;
903 Object newBackground = c2.isBackgroundSet() ? c2.getBackground() : null;
904 if (!Objects.equals(oldBackground, newBackground)) {
905 invokeStatement(oldInstance, "setBackground", new Object[] { oldBackground }, out);
906 }
907 Object oldForeground = c.isForegroundSet() ? c.getForeground() : null;
908 Object newForeground = c2.isForegroundSet() ? c2.getForeground() : null;
909 if (!Objects.equals(oldForeground, newForeground)) {
910 invokeStatement(oldInstance, "setForeground", new Object[] { oldForeground }, out);
911 }
912 Object oldFont = c.isFontSet() ? c.getFont() : null;
913 Object newFont = c2.isFontSet() ? c2.getFont() : null;
914 if (!Objects.equals(oldFont, newFont)) {
915 invokeStatement(oldInstance, "setFont", new Object[] { oldFont }, out);
916 }
917 }
918
919 // Bounds
920 java.awt.Container p = c.getParent();
921 if (p == null || p.getLayout() == null) {
922 // Use the most concise construct.
923 boolean locationCorrect = c.getLocation().equals(c2.getLocation());
924 boolean sizeCorrect = c.getSize().equals(c2.getSize());
925 if (!locationCorrect && !sizeCorrect) {
926 invokeStatement(oldInstance, "setBounds", new Object[]{c.getBounds()}, out);
927 }
928 else if (!locationCorrect) {
929 invokeStatement(oldInstance, "setLocation", new Object[]{c.getLocation()}, out);
930 }
931 else if (!sizeCorrect) {
932 invokeStatement(oldInstance, "setSize", new Object[]{c.getSize()}, out);
933 }
934 }
1291
1292 // it is possible because MatteBorder is assignable from MatteBorderUIResource
1293 internalPersistenceDelegates.put("javax.swing.plaf.BorderUIResource$MatteBorderUIResource",
1294 new javax_swing_border_MatteBorder_PersistenceDelegate());
1295
1296 // it is possible because FontUIResource is supported by java_awt_Font_PersistenceDelegate
1297 internalPersistenceDelegates.put("javax.swing.plaf.FontUIResource",
1298 new java_awt_Font_PersistenceDelegate());
1299
1300 // it is possible because KeyStroke is supported by java_awt_AWTKeyStroke_PersistenceDelegate
1301 internalPersistenceDelegates.put("javax.swing.KeyStroke",
1302 new java_awt_AWTKeyStroke_PersistenceDelegate());
1303
1304 internalPersistenceDelegates.put("java.sql.Date", new java_util_Date_PersistenceDelegate());
1305 internalPersistenceDelegates.put("java.sql.Time", new java_util_Date_PersistenceDelegate());
1306
1307 internalPersistenceDelegates.put("java.util.JumboEnumSet", new java_util_EnumSet_PersistenceDelegate());
1308 internalPersistenceDelegates.put("java.util.RegularEnumSet", new java_util_EnumSet_PersistenceDelegate());
1309 }
1310
1311 public synchronized static PersistenceDelegate getPersistenceDelegate(Class type) {
1312 if (type == null) {
1313 return nullPersistenceDelegate;
1314 }
1315 if (Enum.class.isAssignableFrom(type)) {
1316 return enumPersistenceDelegate;
1317 }
1318 if (ReflectionUtils.isPrimitive(type)) {
1319 return primitivePersistenceDelegate;
1320 }
1321 // The persistence delegate for arrays is non-trivial; instantiate it lazily.
1322 if (type.isArray()) {
1323 if (arrayPersistenceDelegate == null) {
1324 arrayPersistenceDelegate = new ArrayPersistenceDelegate();
1325 }
1326 return arrayPersistenceDelegate;
1327 }
1328 // Handle proxies lazily for backward compatibility with 1.2.
1329 try {
1330 if (java.lang.reflect.Proxy.isProxyClass(type)) {
|