Save This Page
Home » openjdk-7 » java » beans » [javadoc | source]
    1   /*
    2    * Copyright (c) 2000, 2010, 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.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) {
   81       // System.out.println("NullPersistenceDelegate:writeObject " + oldInstance);
   82       }
   83   }
   84   
   85   /**
   86    * The persistence delegate for <CODE>enum</CODE> classes.
   87    *
   88    * @author Sergey A. Malenkov
   89    */
   90   class EnumPersistenceDelegate extends PersistenceDelegate {
   91       protected boolean mutatesTo(Object oldInstance, Object newInstance) {
   92           return oldInstance == newInstance;
   93       }
   94   
   95       protected Expression instantiate(Object oldInstance, Encoder out) {
   96           Enum e = (Enum) oldInstance;
   97           return new Expression(e, Enum.class, "valueOf", new Object[]{e.getDeclaringClass(), e.name()});
   98       }
   99   }
  100   
  101   class PrimitivePersistenceDelegate extends PersistenceDelegate {
  102       protected boolean mutatesTo(Object oldInstance, Object newInstance) {
  103           return oldInstance.equals(newInstance);
  104       }
  105   
  106       protected Expression instantiate(Object oldInstance, Encoder out) {
  107           return new Expression(oldInstance, oldInstance.getClass(),
  108                     "new", new Object[]{oldInstance.toString()});
  109       }
  110   }
  111   
  112   class ArrayPersistenceDelegate extends PersistenceDelegate {
  113       protected boolean mutatesTo(Object oldInstance, Object newInstance) {
  114           return (newInstance != null &&
  115                   oldInstance.getClass() == newInstance.getClass() && // Also ensures the subtype is correct.
  116                   Array.getLength(oldInstance) == Array.getLength(newInstance));
  117           }
  118   
  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);
  160           if (ih instanceof EventHandler) {
  161               EventHandler eh = (EventHandler)ih;
  162               Vector args = new Vector();
  163               args.add(type.getInterfaces()[0]);
  164               args.add(eh.getTarget());
  165               args.add(eh.getAction());
  166               if (eh.getEventPropertyName() != null) {
  167                   args.add(eh.getEventPropertyName());
  168               }
  169               if (eh.getListenerMethodName() != null) {
  170                   args.setSize(4);
  171                   args.add(eh.getListenerMethodName());
  172               }
  173               return new Expression(oldInstance,
  174                                     EventHandler.class,
  175                                     "create",
  176                                     args.toArray());
  177           }
  178           return new Expression(oldInstance,
  179                                 java.lang.reflect.Proxy.class,
  180                                 "newProxyInstance",
  181                                 new Object[]{type.getClassLoader(),
  182                                              type.getInterfaces(),
  183                                              ih});
  184       }
  185   }
  186   
  187   // Strings
  188   class java_lang_String_PersistenceDelegate extends PersistenceDelegate {
  189       protected Expression instantiate(Object oldInstance, Encoder out) { return null; }
  190   
  191       public void writeObject(Object oldInstance, Encoder out) {
  192           // System.out.println("NullPersistenceDelegate:writeObject " + oldInstance);
  193       }
  194   }
  195   
  196   // Classes
  197   class java_lang_Class_PersistenceDelegate extends PersistenceDelegate {
  198       protected boolean mutatesTo(Object oldInstance, Object newInstance) {
  199           return oldInstance.equals(newInstance);
  200       }
  201   
  202       protected Expression instantiate(Object oldInstance, Encoder out) {
  203           Class c = (Class)oldInstance;
  204           // As of 1.3 it is not possible to call Class.forName("int"),
  205           // so we have to generate different code for primitive types.
  206           // This is needed for arrays whose subtype may be primitive.
  207           if (c.isPrimitive()) {
  208               Field field = null;
  209               try {
  210                   field = PrimitiveWrapperMap.getType(c.getName()).getDeclaredField("TYPE");
  211               } catch (NoSuchFieldException ex) {
  212                   System.err.println("Unknown primitive type: " + c);
  213               }
  214               return new Expression(oldInstance, field, "get", new Object[]{null});
  215           }
  216           else if (oldInstance == String.class) {
  217               return new Expression(oldInstance, "", "getClass", new Object[]{});
  218           }
  219           else if (oldInstance == Class.class) {
  220               return new Expression(oldInstance, String.class, "getClass", new Object[]{});
  221           }
  222           else {
  223               Expression newInstance = new Expression(oldInstance, Class.class, "forName", new Object[] { c.getName() });
  224               newInstance.loader = c.getClassLoader();
  225               return newInstance;
  226           }
  227       }
  228   }
  229   
  230   // Fields
  231   class java_lang_reflect_Field_PersistenceDelegate extends PersistenceDelegate {
  232       protected boolean mutatesTo(Object oldInstance, Object newInstance) {
  233           return oldInstance.equals(newInstance);
  234       }
  235   
  236       protected Expression instantiate(Object oldInstance, Encoder out) {
  237           Field f = (Field)oldInstance;
  238           return new Expression(oldInstance,
  239                   f.getDeclaringClass(),
  240                   "getField",
  241                   new Object[]{f.getName()});
  242       }
  243   }
  244   
  245   // Methods
  246   class java_lang_reflect_Method_PersistenceDelegate extends PersistenceDelegate {
  247       protected boolean mutatesTo(Object oldInstance, Object newInstance) {
  248           return oldInstance.equals(newInstance);
  249       }
  250   
  251       protected Expression instantiate(Object oldInstance, Encoder out) {
  252           Method m = (Method)oldInstance;
  253           return new Expression(oldInstance,
  254                   m.getDeclaringClass(),
  255                   "getMethod",
  256                   new Object[]{m.getName(), m.getParameterTypes()});
  257       }
  258   }
  259   
  260   // Dates
  261   
  262   /**
  263    * The persistence delegate for <CODE>java.util.Date</CODE> classes.
  264    * Do not extend DefaultPersistenceDelegate to improve performance and
  265    * to avoid problems with <CODE>java.sql.Date</CODE>,
  266    * <CODE>java.sql.Time</CODE> and <CODE>java.sql.Timestamp</CODE>.
  267    *
  268    * @author Sergey A. Malenkov
  269    */
  270   class java_util_Date_PersistenceDelegate extends PersistenceDelegate {
  271       protected boolean mutatesTo(Object oldInstance, Object newInstance) {
  272           if (!super.mutatesTo(oldInstance, newInstance)) {
  273               return false;
  274           }
  275           Date oldDate = (Date)oldInstance;
  276           Date newDate = (Date)newInstance;
  277   
  278           return oldDate.getTime() == newDate.getTime();
  279       }
  280   
  281       protected Expression instantiate(Object oldInstance, Encoder out) {
  282           Date date = (Date)oldInstance;
  283           return new Expression(date, date.getClass(), "new", new Object[] {date.getTime()});
  284       }
  285   }
  286   
  287   /**
  288    * The persistence delegate for <CODE>java.sql.Timestamp</CODE> classes.
  289    * It supports nanoseconds.
  290    *
  291    * @author Sergey A. Malenkov
  292    */
  293   final class java_sql_Timestamp_PersistenceDelegate extends java_util_Date_PersistenceDelegate {
  294       private static final Method getNanosMethod = getNanosMethod();
  295   
  296       private static Method getNanosMethod() {
  297           try {
  298               Class<?> c = Class.forName("java.sql.Timestamp", true, null);
  299               return c.getMethod("getNanos");
  300           } catch (ClassNotFoundException e) {
  301               return null;
  302           } catch (NoSuchMethodException e) {
  303               throw new AssertionError(e);
  304           }
  305       }
  306   
  307       /**
  308        * Invoke Timstamp getNanos.
  309        */
  310       private static int getNanos(Object obj) {
  311           if (getNanosMethod == null)
  312               throw new AssertionError("Should not get here");
  313           try {
  314               return (Integer)getNanosMethod.invoke(obj);
  315           } catch (InvocationTargetException e) {
  316               Throwable cause = e.getCause();
  317               if (cause instanceof RuntimeException)
  318                   throw (RuntimeException)cause;
  319               if (cause instanceof Error)
  320                   throw (Error)cause;
  321               throw new AssertionError(e);
  322           } catch (IllegalAccessException iae) {
  323               throw new AssertionError(iae);
  324           }
  325       }
  326   
  327       protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
  328           // assumes oldInstance and newInstance are Timestamps
  329           int nanos = getNanos(oldInstance);
  330           if (nanos != getNanos(newInstance)) {
  331               out.writeStatement(new Statement(oldInstance, "setNanos", new Object[] {nanos}));
  332           }
  333       }
  334   }
  335   
  336   // Collections
  337   
  338   /*
  339   The Hashtable and AbstractMap classes have no common ancestor yet may
  340   be handled with a single persistence delegate: one which uses the methods
  341   of the Map insterface exclusively. Attatching the persistence delegates
  342   to the interfaces themselves is fraught however since, in the case of
  343   the Map, both the AbstractMap and HashMap classes are declared to
  344   implement the Map interface, leaving the obvious implementation prone
  345   to repeating their initialization. These issues and questions around
  346   the ordering of delegates attached to interfaces have lead us to
  347   ignore any delegates attached to interfaces and force all persistence
  348   delegates to be registered with concrete classes.
  349   */
  350   
  351   /**
  352    * The base class for persistence delegates for inner classes
  353    * that can be created using {@link Collections}.
  354    *
  355    * @author Sergey A. Malenkov
  356    */
  357   abstract class java_util_Collections extends PersistenceDelegate {
  358       protected boolean mutatesTo(Object oldInstance, Object newInstance) {
  359           if (!super.mutatesTo(oldInstance, newInstance)) {
  360               return false;
  361           }
  362           if ((oldInstance instanceof List) || (oldInstance instanceof Set) || (oldInstance instanceof Map)) {
  363               return oldInstance.equals(newInstance);
  364           }
  365           Collection oldC = (Collection) oldInstance;
  366           Collection newC = (Collection) newInstance;
  367           return (oldC.size() == newC.size()) && oldC.containsAll(newC);
  368       }
  369   
  370       static final class EmptyList_PersistenceDelegate extends java_util_Collections {
  371           protected Expression instantiate(Object oldInstance, Encoder out) {
  372               return new Expression(oldInstance, Collections.class, "emptyList", null);
  373           }
  374       }
  375   
  376       static final class EmptySet_PersistenceDelegate extends java_util_Collections {
  377           protected Expression instantiate(Object oldInstance, Encoder out) {
  378               return new Expression(oldInstance, Collections.class, "emptySet", null);
  379           }
  380       }
  381   
  382       static final class EmptyMap_PersistenceDelegate extends java_util_Collections {
  383           protected Expression instantiate(Object oldInstance, Encoder out) {
  384               return new Expression(oldInstance, Collections.class, "emptyMap", null);
  385           }
  386       }
  387   
  388       static final class SingletonList_PersistenceDelegate extends java_util_Collections {
  389           protected Expression instantiate(Object oldInstance, Encoder out) {
  390               List list = (List) oldInstance;
  391               return new Expression(oldInstance, Collections.class, "singletonList", new Object[]{list.get(0)});
  392           }
  393       }
  394   
  395       static final class SingletonSet_PersistenceDelegate extends java_util_Collections {
  396           protected Expression instantiate(Object oldInstance, Encoder out) {
  397               Set set = (Set) oldInstance;
  398               return new Expression(oldInstance, Collections.class, "singleton", new Object[]{set.iterator().next()});
  399           }
  400       }
  401   
  402       static final class SingletonMap_PersistenceDelegate extends java_util_Collections {
  403           protected Expression instantiate(Object oldInstance, Encoder out) {
  404               Map map = (Map) oldInstance;
  405               Object key = map.keySet().iterator().next();
  406               return new Expression(oldInstance, Collections.class, "singletonMap", new Object[]{key, map.get(key)});
  407           }
  408       }
  409   
  410       static final class UnmodifiableCollection_PersistenceDelegate extends java_util_Collections {
  411           protected Expression instantiate(Object oldInstance, Encoder out) {
  412               List list = new ArrayList((Collection) oldInstance);
  413               return new Expression(oldInstance, Collections.class, "unmodifiableCollection", new Object[]{list});
  414           }
  415       }
  416   
  417       static final class UnmodifiableList_PersistenceDelegate extends java_util_Collections {
  418           protected Expression instantiate(Object oldInstance, Encoder out) {
  419               List list = new LinkedList((Collection) oldInstance);
  420               return new Expression(oldInstance, Collections.class, "unmodifiableList", new Object[]{list});
  421           }
  422       }
  423   
  424       static final class UnmodifiableRandomAccessList_PersistenceDelegate extends java_util_Collections {
  425           protected Expression instantiate(Object oldInstance, Encoder out) {
  426               List list = new ArrayList((Collection) oldInstance);
  427               return new Expression(oldInstance, Collections.class, "unmodifiableList", new Object[]{list});
  428           }
  429       }
  430   
  431       static final class UnmodifiableSet_PersistenceDelegate extends java_util_Collections {
  432           protected Expression instantiate(Object oldInstance, Encoder out) {
  433               Set set = new HashSet((Set) oldInstance);
  434               return new Expression(oldInstance, Collections.class, "unmodifiableSet", new Object[]{set});
  435           }
  436       }
  437   
  438       static final class UnmodifiableSortedSet_PersistenceDelegate extends java_util_Collections {
  439           protected Expression instantiate(Object oldInstance, Encoder out) {
  440               SortedSet set = new TreeSet((SortedSet) oldInstance);
  441               return new Expression(oldInstance, Collections.class, "unmodifiableSortedSet", new Object[]{set});
  442           }
  443       }
  444   
  445       static final class UnmodifiableMap_PersistenceDelegate extends java_util_Collections {
  446           protected Expression instantiate(Object oldInstance, Encoder out) {
  447               Map map = new HashMap((Map) oldInstance);
  448               return new Expression(oldInstance, Collections.class, "unmodifiableMap", new Object[]{map});
  449           }
  450       }
  451   
  452       static final class UnmodifiableSortedMap_PersistenceDelegate extends java_util_Collections {
  453           protected Expression instantiate(Object oldInstance, Encoder out) {
  454               SortedMap map = new TreeMap((SortedMap) oldInstance);
  455               return new Expression(oldInstance, Collections.class, "unmodifiableSortedMap", new Object[]{map});
  456           }
  457       }
  458   
  459       static final class SynchronizedCollection_PersistenceDelegate extends java_util_Collections {
  460           protected Expression instantiate(Object oldInstance, Encoder out) {
  461               List list = new ArrayList((Collection) oldInstance);
  462               return new Expression(oldInstance, Collections.class, "synchronizedCollection", new Object[]{list});
  463           }
  464       }
  465   
  466       static final class SynchronizedList_PersistenceDelegate extends java_util_Collections {
  467           protected Expression instantiate(Object oldInstance, Encoder out) {
  468               List list = new LinkedList((Collection) oldInstance);
  469               return new Expression(oldInstance, Collections.class, "synchronizedList", new Object[]{list});
  470           }
  471       }
  472   
  473       static final class SynchronizedRandomAccessList_PersistenceDelegate extends java_util_Collections {
  474           protected Expression instantiate(Object oldInstance, Encoder out) {
  475               List list = new ArrayList((Collection) oldInstance);
  476               return new Expression(oldInstance, Collections.class, "synchronizedList", new Object[]{list});
  477           }
  478       }
  479   
  480       static final class SynchronizedSet_PersistenceDelegate extends java_util_Collections {
  481           protected Expression instantiate(Object oldInstance, Encoder out) {
  482               Set set = new HashSet((Set) oldInstance);
  483               return new Expression(oldInstance, Collections.class, "synchronizedSet", new Object[]{set});
  484           }
  485       }
  486   
  487       static final class SynchronizedSortedSet_PersistenceDelegate extends java_util_Collections {
  488           protected Expression instantiate(Object oldInstance, Encoder out) {
  489               SortedSet set = new TreeSet((SortedSet) oldInstance);
  490               return new Expression(oldInstance, Collections.class, "synchronizedSortedSet", new Object[]{set});
  491           }
  492       }
  493   
  494       static final class SynchronizedMap_PersistenceDelegate extends java_util_Collections {
  495           protected Expression instantiate(Object oldInstance, Encoder out) {
  496               Map map = new HashMap((Map) oldInstance);
  497               return new Expression(oldInstance, Collections.class, "synchronizedMap", new Object[]{map});
  498           }
  499       }
  500   
  501       static final class SynchronizedSortedMap_PersistenceDelegate extends java_util_Collections {
  502           protected Expression instantiate(Object oldInstance, Encoder out) {
  503               SortedMap map = new TreeMap((SortedMap) oldInstance);
  504               return new Expression(oldInstance, Collections.class, "synchronizedSortedMap", new Object[]{map});
  505           }
  506       }
  507   
  508       static final class CheckedCollection_PersistenceDelegate extends java_util_Collections {
  509           protected Expression instantiate(Object oldInstance, Encoder out) {
  510               Object type = MetaData.getPrivateFieldValue(oldInstance, "java.util.Collections$CheckedCollection.type");
  511               List list = new ArrayList((Collection) oldInstance);
  512               return new Expression(oldInstance, Collections.class, "checkedCollection", new Object[]{list, type});
  513           }
  514       }
  515   
  516       static final class CheckedList_PersistenceDelegate extends java_util_Collections {
  517           protected Expression instantiate(Object oldInstance, Encoder out) {
  518               Object type = MetaData.getPrivateFieldValue(oldInstance, "java.util.Collections$CheckedCollection.type");
  519               List list = new LinkedList((Collection) oldInstance);
  520               return new Expression(oldInstance, Collections.class, "checkedList", new Object[]{list, type});
  521           }
  522       }
  523   
  524       static final class CheckedRandomAccessList_PersistenceDelegate extends java_util_Collections {
  525           protected Expression instantiate(Object oldInstance, Encoder out) {
  526               Object type = MetaData.getPrivateFieldValue(oldInstance, "java.util.Collections$CheckedCollection.type");
  527               List list = new ArrayList((Collection) oldInstance);
  528               return new Expression(oldInstance, Collections.class, "checkedList", new Object[]{list, type});
  529           }
  530       }
  531   
  532       static final class CheckedSet_PersistenceDelegate extends java_util_Collections {
  533           protected Expression instantiate(Object oldInstance, Encoder out) {
  534               Object type = MetaData.getPrivateFieldValue(oldInstance, "java.util.Collections$CheckedCollection.type");
  535               Set set = new HashSet((Set) oldInstance);
  536               return new Expression(oldInstance, Collections.class, "checkedSet", new Object[]{set, type});
  537           }
  538       }
  539   
  540       static final class CheckedSortedSet_PersistenceDelegate extends java_util_Collections {
  541           protected Expression instantiate(Object oldInstance, Encoder out) {
  542               Object type = MetaData.getPrivateFieldValue(oldInstance, "java.util.Collections$CheckedCollection.type");
  543               SortedSet set = new TreeSet((SortedSet) oldInstance);
  544               return new Expression(oldInstance, Collections.class, "checkedSortedSet", new Object[]{set, type});
  545           }
  546       }
  547   
  548       static final class CheckedMap_PersistenceDelegate extends java_util_Collections {
  549           protected Expression instantiate(Object oldInstance, Encoder out) {
  550               Object keyType   = MetaData.getPrivateFieldValue(oldInstance, "java.util.Collections$CheckedMap.keyType");
  551               Object valueType = MetaData.getPrivateFieldValue(oldInstance, "java.util.Collections$CheckedMap.valueType");
  552               Map map = new HashMap((Map) oldInstance);
  553               return new Expression(oldInstance, Collections.class, "checkedMap", new Object[]{map, keyType, valueType});
  554           }
  555       }
  556   
  557       static final class CheckedSortedMap_PersistenceDelegate extends java_util_Collections {
  558           protected Expression instantiate(Object oldInstance, Encoder out) {
  559               Object keyType   = MetaData.getPrivateFieldValue(oldInstance, "java.util.Collections$CheckedMap.keyType");
  560               Object valueType = MetaData.getPrivateFieldValue(oldInstance, "java.util.Collections$CheckedMap.valueType");
  561               SortedMap map = new TreeMap((SortedMap) oldInstance);
  562               return new Expression(oldInstance, Collections.class, "checkedSortedMap", new Object[]{map, keyType, valueType});
  563           }
  564       }
  565   }
  566   
  567   /**
  568    * The persistence delegate for <CODE>java.util.EnumMap</CODE> classes.
  569    *
  570    * @author Sergey A. Malenkov
  571    */
  572   class java_util_EnumMap_PersistenceDelegate extends PersistenceDelegate {
  573       protected boolean mutatesTo(Object oldInstance, Object newInstance) {
  574           return super.mutatesTo(oldInstance, newInstance) && (getType(oldInstance) == getType(newInstance));
  575       }
  576   
  577       protected Expression instantiate(Object oldInstance, Encoder out) {
  578           return new Expression(oldInstance, EnumMap.class, "new", new Object[] {getType(oldInstance)});
  579       }
  580   
  581       private static Object getType(Object instance) {
  582           return MetaData.getPrivateFieldValue(instance, "java.util.EnumMap.keyType");
  583       }
  584   }
  585   
  586   /**
  587    * The persistence delegate for <CODE>java.util.EnumSet</CODE> classes.
  588    *
  589    * @author Sergey A. Malenkov
  590    */
  591   class java_util_EnumSet_PersistenceDelegate extends PersistenceDelegate {
  592       protected boolean mutatesTo(Object oldInstance, Object newInstance) {
  593           return super.mutatesTo(oldInstance, newInstance) && (getType(oldInstance) == getType(newInstance));
  594       }
  595   
  596       protected Expression instantiate(Object oldInstance, Encoder out) {
  597           return new Expression(oldInstance, EnumSet.class, "noneOf", new Object[] {getType(oldInstance)});
  598       }
  599   
  600       private static Object getType(Object instance) {
  601           return MetaData.getPrivateFieldValue(instance, "java.util.EnumSet.elementType");
  602       }
  603   }
  604   
  605   // Collection
  606   class java_util_Collection_PersistenceDelegate extends DefaultPersistenceDelegate {
  607       protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
  608           java.util.Collection oldO = (java.util.Collection)oldInstance;
  609           java.util.Collection newO = (java.util.Collection)newInstance;
  610   
  611           if (newO.size() != 0) {
  612               invokeStatement(oldInstance, "clear", new Object[]{}, out);
  613           }
  614           for (Iterator i = oldO.iterator(); i.hasNext();) {
  615               invokeStatement(oldInstance, "add", new Object[]{i.next()}, out);
  616           }
  617       }
  618   }
  619   
  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
  701   class java_beans_beancontext_BeanContextSupport_PersistenceDelegate extends java_util_Collection_PersistenceDelegate {}
  702   
  703   // AWT
  704   
  705   /**
  706    * The persistence delegate for {@link Insets}.
  707    * It is impossible to use {@link DefaultPersistenceDelegate}
  708    * because this class does not have any properties.
  709    *
  710    * @author Sergey A. Malenkov
  711    */
  712   final class java_awt_Insets_PersistenceDelegate extends PersistenceDelegate {
  713       protected boolean mutatesTo(Object oldInstance, Object newInstance) {
  714           return oldInstance.equals(newInstance);
  715       }
  716   
  717       protected Expression instantiate(Object oldInstance, Encoder out) {
  718           Insets insets = (Insets) oldInstance;
  719           Object[] args = new Object[] {
  720                   insets.top,
  721                   insets.left,
  722                   insets.bottom,
  723                   insets.right,
  724           };
  725           return new Expression(insets, insets.getClass(), "new", args);
  726       }
  727   }
  728   
  729   /**
  730    * The persistence delegate for {@link Font}.
  731    * It is impossible to use {@link DefaultPersistenceDelegate}
  732    * because size of the font can be float value.
  733    *
  734    * @author Sergey A. Malenkov
  735    */
  736   final class java_awt_Font_PersistenceDelegate extends PersistenceDelegate {
  737       protected boolean mutatesTo(Object oldInstance, Object newInstance) {
  738           return oldInstance.equals(newInstance);
  739       }
  740   
  741       protected Expression instantiate(Object oldInstance, Encoder out) {
  742           Font font = (Font) oldInstance;
  743   
  744           int count = 0;
  745           String family = null;
  746           int style = Font.PLAIN;
  747           int size = 12;
  748   
  749           Map basic = font.getAttributes();
  750           Map clone = new HashMap(basic.size());
  751           for (Object key : basic.keySet()) {
  752               Object value = basic.get(key);
  753               if (value != null) {
  754                   clone.put(key, value);
  755               }
  756               if (key == TextAttribute.FAMILY) {
  757                   if (value instanceof String) {
  758                       count++;
  759                       family = (String) value;
  760                   }
  761               }
  762               else if (key == TextAttribute.WEIGHT) {
  763                   if (TextAttribute.WEIGHT_REGULAR.equals(value)) {
  764                       count++;
  765                   } else if (TextAttribute.WEIGHT_BOLD.equals(value)) {
  766                       count++;
  767                       style |= Font.BOLD;
  768                   }
  769               }
  770               else if (key == TextAttribute.POSTURE) {
  771                   if (TextAttribute.POSTURE_REGULAR.equals(value)) {
  772                       count++;
  773                   } else if (TextAttribute.POSTURE_OBLIQUE.equals(value)) {
  774                       count++;
  775                       style |= Font.ITALIC;
  776                   }
  777               } else if (key == TextAttribute.SIZE) {
  778                   if (value instanceof Number) {
  779                       Number number = (Number) value;
  780                       size = number.intValue();
  781                       if (size == number.floatValue()) {
  782                           count++;
  783                       }
  784                   }
  785               }
  786           }
  787           Class type = font.getClass();
  788           if (count == clone.size()) {
  789               return new Expression(font, type, "new", new Object[]{family, style, size});
  790           }
  791           if (type == Font.class) {
  792               return new Expression(font, type, "getFont", new Object[]{clone});
  793           }
  794           return new Expression(font, type, "new", new Object[]{Font.getFont(clone)});
  795       }
  796   }
  797   
  798   /**
  799    * The persistence delegate for {@link AWTKeyStroke}.
  800    * It is impossible to use {@link DefaultPersistenceDelegate}
  801    * because this class have no public constructor.
  802    *
  803    * @author Sergey A. Malenkov
  804    */
  805   final class java_awt_AWTKeyStroke_PersistenceDelegate extends PersistenceDelegate {
  806       protected boolean mutatesTo(Object oldInstance, Object newInstance) {
  807           return oldInstance.equals(newInstance);
  808       }
  809   
  810       protected Expression instantiate(Object oldInstance, Encoder out) {
  811           AWTKeyStroke key = (AWTKeyStroke) oldInstance;
  812   
  813           char ch = key.getKeyChar();
  814           int code = key.getKeyCode();
  815           int mask = key.getModifiers();
  816           boolean onKeyRelease = key.isOnKeyRelease();
  817   
  818           Object[] args = null;
  819           if (ch == KeyEvent.CHAR_UNDEFINED) {
  820               args = !onKeyRelease
  821                       ? new Object[]{code, mask}
  822                       : new Object[]{code, mask, onKeyRelease};
  823           } else if (code == KeyEvent.VK_UNDEFINED) {
  824               if (!onKeyRelease) {
  825                   args = (mask == 0)
  826                           ? new Object[]{ch}
  827                           : new Object[]{ch, mask};
  828               } else if (mask == 0) {
  829                   args = new Object[]{ch, onKeyRelease};
  830               }
  831           }
  832           if (args == null) {
  833               throw new IllegalStateException("Unsupported KeyStroke: " + key);
  834           }
  835           Class type = key.getClass();
  836           String name = type.getName();
  837           // get short name of the class
  838           int index = name.lastIndexOf('.') + 1;
  839           if (index > 0) {
  840               name = name.substring(index);
  841           }
  842           return new Expression( key, type, "get" + name, args );
  843       }
  844   }
  845   
  846   class StaticFieldsPersistenceDelegate extends PersistenceDelegate {
  847       protected void installFields(Encoder out, Class<?> cls) {
  848           Field fields[] = cls.getFields();
  849           for(int i = 0; i < fields.length; i++) {
  850               Field field = fields[i];
  851               // Don't install primitives, their identity will not be preserved
  852               // by wrapping.
  853               if (Object.class.isAssignableFrom(field.getType())) {
  854                   out.writeExpression(new Expression(field, "get", new Object[]{null}));
  855               }
  856           }
  857       }
  858   
  859       protected Expression instantiate(Object oldInstance, Encoder out) {
  860           throw new RuntimeException("Unrecognized instance: " + oldInstance);
  861       }
  862   
  863       public void writeObject(Object oldInstance, Encoder out) {
  864           if (out.getAttribute(this) == null) {
  865               out.setAttribute(this, Boolean.TRUE);
  866               installFields(out, oldInstance.getClass());
  867           }
  868           super.writeObject(oldInstance, out);
  869       }
  870   }
  871   
  872   // SystemColor
  873   class java_awt_SystemColor_PersistenceDelegate extends StaticFieldsPersistenceDelegate {}
  874   
  875   // TextAttribute
  876   class java_awt_font_TextAttribute_PersistenceDelegate extends StaticFieldsPersistenceDelegate {}
  877   
  878   // MenuShortcut
  879   class java_awt_MenuShortcut_PersistenceDelegate extends PersistenceDelegate {
  880       protected boolean mutatesTo(Object oldInstance, Object newInstance) {
  881           return oldInstance.equals(newInstance);
  882       }
  883   
  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           }
  935       }
  936   }
  937   
  938   // Container
  939   class java_awt_Container_PersistenceDelegate extends DefaultPersistenceDelegate {
  940       protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
  941           super.initialize(type, oldInstance, newInstance, out);
  942           // Ignore the children of a JScrollPane.
  943           // Pending(milne) find a better way to do this.
  944           if (oldInstance instanceof javax.swing.JScrollPane) {
  945               return;
  946           }
  947           java.awt.Container oldC = (java.awt.Container)oldInstance;
  948           java.awt.Component[] oldChildren = oldC.getComponents();
  949           java.awt.Container newC = (java.awt.Container)newInstance;
  950           java.awt.Component[] newChildren = (newC == null) ? new java.awt.Component[0] : newC.getComponents();
  951   
  952           BorderLayout layout = ( oldC.getLayout() instanceof BorderLayout )
  953                   ? ( BorderLayout )oldC.getLayout()
  954                   : null;
  955   
  956           JLayeredPane oldLayeredPane = (oldInstance instanceof JLayeredPane)
  957                   ? (JLayeredPane) oldInstance
  958                   : null;
  959   
  960           // Pending. Assume all the new children are unaltered.
  961           for(int i = newChildren.length; i < oldChildren.length; i++) {
  962               Object[] args = ( layout != null )
  963                       ? new Object[] {oldChildren[i], layout.getConstraints( oldChildren[i] )}
  964                       : (oldLayeredPane != null)
  965                               ? new Object[] {oldChildren[i], oldLayeredPane.getLayer(oldChildren[i]), Integer.valueOf(-1)}
  966                               : new Object[] {oldChildren[i]};
  967   
  968               invokeStatement(oldInstance, "add", args, out);
  969           }
  970       }
  971   }
  972   
  973   // Choice
  974   class java_awt_Choice_PersistenceDelegate extends DefaultPersistenceDelegate {
  975       protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
  976           super.initialize(type, oldInstance, newInstance, out);
  977           java.awt.Choice m = (java.awt.Choice)oldInstance;
  978           java.awt.Choice n = (java.awt.Choice)newInstance;
  979           for (int i = n.getItemCount(); i < m.getItemCount(); i++) {
  980               invokeStatement(oldInstance, "add", new Object[]{m.getItem(i)}, out);
  981           }
  982       }
  983   }
  984   
  985   // Menu
  986   class java_awt_Menu_PersistenceDelegate extends DefaultPersistenceDelegate {
  987       protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
  988           super.initialize(type, oldInstance, newInstance, out);
  989           java.awt.Menu m = (java.awt.Menu)oldInstance;
  990           java.awt.Menu n = (java.awt.Menu)newInstance;
  991           for (int i = n.getItemCount(); i < m.getItemCount(); i++) {
  992               invokeStatement(oldInstance, "add", new Object[]{m.getItem(i)}, out);
  993           }
  994       }
  995   }
  996   
  997   // MenuBar
  998   class java_awt_MenuBar_PersistenceDelegate extends DefaultPersistenceDelegate {
  999       protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
 1000           super.initialize(type, oldInstance, newInstance, out);
 1001           java.awt.MenuBar m = (java.awt.MenuBar)oldInstance;
 1002           java.awt.MenuBar n = (java.awt.MenuBar)newInstance;
 1003           for (int i = n.getMenuCount(); i < m.getMenuCount(); i++) {
 1004               invokeStatement(oldInstance, "add", new Object[]{m.getMenu(i)}, out);
 1005           }
 1006       }
 1007   }
 1008   
 1009   // List
 1010   class java_awt_List_PersistenceDelegate extends DefaultPersistenceDelegate {
 1011       protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
 1012           super.initialize(type, oldInstance, newInstance, out);
 1013           java.awt.List m = (java.awt.List)oldInstance;
 1014           java.awt.List n = (java.awt.List)newInstance;
 1015           for (int i = n.getItemCount(); i < m.getItemCount(); i++) {
 1016               invokeStatement(oldInstance, "add", new Object[]{m.getItem(i)}, out);
 1017           }
 1018       }
 1019   }
 1020   
 1021   
 1022   // LayoutManagers
 1023   
 1024   // BorderLayout
 1025   class java_awt_BorderLayout_PersistenceDelegate extends DefaultPersistenceDelegate {
 1026       private static final String[] CONSTRAINTS = {
 1027               BorderLayout.NORTH,
 1028               BorderLayout.SOUTH,
 1029               BorderLayout.EAST,
 1030               BorderLayout.WEST,
 1031               BorderLayout.CENTER,
 1032               BorderLayout.PAGE_START,
 1033               BorderLayout.PAGE_END,
 1034               BorderLayout.LINE_START,
 1035               BorderLayout.LINE_END,
 1036       };
 1037       @Override
 1038       protected void initialize(Class<?> type, Object oldInstance,
 1039                                 Object newInstance, Encoder out) {
 1040           super.initialize(type, oldInstance, newInstance, out);
 1041           BorderLayout oldLayout = (BorderLayout) oldInstance;
 1042           BorderLayout newLayout = (BorderLayout) newInstance;
 1043           for (String constraints : CONSTRAINTS) {
 1044               Object oldC = oldLayout.getLayoutComponent(constraints);
 1045               Object newC = newLayout.getLayoutComponent(constraints);
 1046               // Pending, assume any existing elements are OK.
 1047               if (oldC != null && newC == null) {
 1048                   invokeStatement(oldInstance, "addLayoutComponent",
 1049                                   new Object[] { oldC, constraints }, out);
 1050               }
 1051           }
 1052       }
 1053   }
 1054   
 1055   // CardLayout
 1056   class java_awt_CardLayout_PersistenceDelegate extends DefaultPersistenceDelegate {
 1057       protected void initialize(Class<?> type, Object oldInstance,
 1058                                 Object newInstance, Encoder out) {
 1059           super.initialize(type, oldInstance, newInstance, out);
 1060           Hashtable tab = (Hashtable)ReflectionUtils.getPrivateField(oldInstance,
 1061                                                                      java.awt.CardLayout.class,
 1062                                                                      "tab",
 1063                                                                      out.getExceptionListener());
 1064           if (tab != null) {
 1065               for(Enumeration e = tab.keys(); e.hasMoreElements();) {
 1066                   Object child = e.nextElement();
 1067                   invokeStatement(oldInstance, "addLayoutComponent",
 1068                                   new Object[]{child, (String)tab.get(child)}, out);
 1069               }
 1070           }
 1071       }
 1072   }
 1073   
 1074   // GridBagLayout
 1075   class java_awt_GridBagLayout_PersistenceDelegate extends DefaultPersistenceDelegate {
 1076       protected void initialize(Class<?> type, Object oldInstance,
 1077                                 Object newInstance, Encoder out) {
 1078           super.initialize(type, oldInstance, newInstance, out);
 1079           Hashtable comptable = (Hashtable)ReflectionUtils.getPrivateField(oldInstance,
 1080                                                    java.awt.GridBagLayout.class,
 1081                                                    "comptable",
 1082                                                    out.getExceptionListener());
 1083           if (comptable != null) {
 1084               for(Enumeration e = comptable.keys(); e.hasMoreElements();) {
 1085                   Object child = e.nextElement();
 1086                   invokeStatement(oldInstance, "addLayoutComponent",
 1087                                   new Object[]{child, comptable.get(child)}, out);
 1088               }
 1089           }
 1090       }
 1091   }
 1092   
 1093   // Swing
 1094   
 1095   // JFrame (If we do this for Window instead of JFrame, the setVisible call
 1096   // will be issued before we have added all the children to the JFrame and
 1097   // will appear blank).
 1098   class javax_swing_JFrame_PersistenceDelegate extends DefaultPersistenceDelegate {
 1099       protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
 1100           super.initialize(type, oldInstance, newInstance, out);
 1101           java.awt.Window oldC = (java.awt.Window)oldInstance;
 1102           java.awt.Window newC = (java.awt.Window)newInstance;
 1103           boolean oldV = oldC.isVisible();
 1104           boolean newV = newC.isVisible();
 1105           if (newV != oldV) {
 1106               // false means: don't execute this statement at write time.
 1107               boolean executeStatements = out.executeStatements;
 1108               out.executeStatements = false;
 1109               invokeStatement(oldInstance, "setVisible", new Object[]{Boolean.valueOf(oldV)}, out);
 1110               out.executeStatements = executeStatements;
 1111           }
 1112       }
 1113   }
 1114   
 1115   // Models
 1116   
 1117   // DefaultListModel
 1118   class javax_swing_DefaultListModel_PersistenceDelegate extends DefaultPersistenceDelegate {
 1119       protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
 1120           // Note, the "size" property will be set here.
 1121           super.initialize(type, oldInstance, newInstance, out);
 1122           javax.swing.DefaultListModel m = (javax.swing.DefaultListModel)oldInstance;
 1123           javax.swing.DefaultListModel n = (javax.swing.DefaultListModel)newInstance;
 1124           for (int i = n.getSize(); i < m.getSize(); i++) {
 1125               invokeStatement(oldInstance, "add", // Can also use "addElement".
 1126                       new Object[]{m.getElementAt(i)}, out);
 1127           }
 1128       }
 1129   }
 1130   
 1131   // DefaultComboBoxModel
 1132   class javax_swing_DefaultComboBoxModel_PersistenceDelegate extends DefaultPersistenceDelegate {
 1133       protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
 1134           super.initialize(type, oldInstance, newInstance, out);
 1135           javax.swing.DefaultComboBoxModel m = (javax.swing.DefaultComboBoxModel)oldInstance;
 1136           for (int i = 0; i < m.getSize(); i++) {
 1137               invokeStatement(oldInstance, "addElement", new Object[]{m.getElementAt(i)}, out);
 1138           }
 1139       }
 1140   }
 1141   
 1142   
 1143   // DefaultMutableTreeNode
 1144   class javax_swing_tree_DefaultMutableTreeNode_PersistenceDelegate extends DefaultPersistenceDelegate {
 1145       protected void initialize(Class<?> type, Object oldInstance, Object
 1146                                 newInstance, Encoder out) {
 1147           super.initialize(type, oldInstance, newInstance, out);
 1148           javax.swing.tree.DefaultMutableTreeNode m =
 1149               (javax.swing.tree.DefaultMutableTreeNode)oldInstance;
 1150           javax.swing.tree.DefaultMutableTreeNode n =
 1151               (javax.swing.tree.DefaultMutableTreeNode)newInstance;
 1152           for (int i = n.getChildCount(); i < m.getChildCount(); i++) {
 1153               invokeStatement(oldInstance, "add", new
 1154                   Object[]{m.getChildAt(i)}, out);
 1155           }
 1156       }
 1157   }
 1158   
 1159   // ToolTipManager
 1160   class javax_swing_ToolTipManager_PersistenceDelegate extends PersistenceDelegate {
 1161       protected Expression instantiate(Object oldInstance, Encoder out) {
 1162           return new Expression(oldInstance, javax.swing.ToolTipManager.class,
 1163                                 "sharedInstance", new Object[]{});
 1164       }
 1165   }
 1166   
 1167   // JTabbedPane
 1168   class javax_swing_JTabbedPane_PersistenceDelegate extends DefaultPersistenceDelegate {
 1169       protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
 1170           super.initialize(type, oldInstance, newInstance, out);
 1171           javax.swing.JTabbedPane p = (javax.swing.JTabbedPane)oldInstance;
 1172           for (int i = 0; i < p.getTabCount(); i++) {
 1173               invokeStatement(oldInstance, "addTab",
 1174                                             new Object[]{
 1175                                                 p.getTitleAt(i),
 1176                                                 p.getIconAt(i),
 1177                                                 p.getComponentAt(i)}, out);
 1178           }
 1179       }
 1180   }
 1181   
 1182   // Box
 1183   class javax_swing_Box_PersistenceDelegate extends DefaultPersistenceDelegate {
 1184       protected boolean mutatesTo(Object oldInstance, Object newInstance) {
 1185           return super.mutatesTo(oldInstance, newInstance) && getAxis(oldInstance).equals(getAxis(newInstance));
 1186       }
 1187   
 1188       protected Expression instantiate(Object oldInstance, Encoder out) {
 1189           return new Expression(oldInstance, oldInstance.getClass(), "new", new Object[] {getAxis(oldInstance)});
 1190       }
 1191   
 1192       private Integer getAxis(Object object) {
 1193           Box box = (Box) object;
 1194           return (Integer) MetaData.getPrivateFieldValue(box.getLayout(), "javax.swing.BoxLayout.axis");
 1195       }
 1196   }
 1197   
 1198   // JMenu
 1199   // Note that we do not need to state the initialiser for
 1200   // JMenuItems since the getComponents() method defined in
 1201   // Container will return all of the sub menu items that
 1202   // need to be added to the menu item.
 1203   // Not so for JMenu apparently.
 1204   class javax_swing_JMenu_PersistenceDelegate extends DefaultPersistenceDelegate {
 1205       protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
 1206           super.initialize(type, oldInstance, newInstance, out);
 1207           javax.swing.JMenu m = (javax.swing.JMenu)oldInstance;
 1208           java.awt.Component[] c = m.getMenuComponents();
 1209           for (int i = 0; i < c.length; i++) {
 1210               invokeStatement(oldInstance, "add", new Object[]{c[i]}, out);
 1211           }
 1212       }
 1213   }
 1214   
 1215   /**
 1216    * The persistence delegate for {@link MatteBorder}.
 1217    * It is impossible to use {@link DefaultPersistenceDelegate}
 1218    * because this class does not have writable properties.
 1219    *
 1220    * @author Sergey A. Malenkov
 1221    */
 1222   final class javax_swing_border_MatteBorder_PersistenceDelegate extends PersistenceDelegate {
 1223       protected Expression instantiate(Object oldInstance, Encoder out) {
 1224           MatteBorder border = (MatteBorder) oldInstance;
 1225           Insets insets = border.getBorderInsets();
 1226           Object object = border.getTileIcon();
 1227           if (object == null) {
 1228               object = border.getMatteColor();
 1229           }
 1230           Object[] args = new Object[] {
 1231                   insets.top,
 1232                   insets.left,
 1233                   insets.bottom,
 1234                   insets.right,
 1235                   object,
 1236           };
 1237           return new Expression(border, border.getClass(), "new", args);
 1238       }
 1239   }
 1240   
 1241   /* XXX - doens't seem to work. Debug later.
 1242   class javax_swing_JMenu_PersistenceDelegate extends DefaultPersistenceDelegate {
 1243       protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
 1244           super.initialize(type, oldInstance, newInstance, out);
 1245           javax.swing.JMenu m = (javax.swing.JMenu)oldInstance;
 1246           javax.swing.JMenu n = (javax.swing.JMenu)newInstance;
 1247           for (int i = n.getItemCount(); i < m.getItemCount(); i++) {
 1248               invokeStatement(oldInstance, "add", new Object[]{m.getItem(i)}, out);
 1249           }
 1250       }
 1251   }
 1252   */
 1253   
 1254   /**
 1255    * The persistence delegate for {@link PrintColorUIResource}.
 1256    * It is impossible to use {@link DefaultPersistenceDelegate}
 1257    * because this class has special rule for serialization:
 1258    * it should be converted to {@link ColorUIResource}.
 1259    *
 1260    * @see PrintColorUIResource#writeReplace
 1261    *
 1262    * @author Sergey A. Malenkov
 1263    */
 1264   final class sun_swing_PrintColorUIResource_PersistenceDelegate extends PersistenceDelegate {
 1265       protected boolean mutatesTo(Object oldInstance, Object newInstance) {
 1266           return oldInstance.equals(newInstance);
 1267       }
 1268   
 1269       protected Expression instantiate(Object oldInstance, Encoder out) {
 1270           Color color = (Color) oldInstance;
 1271           Object[] args = new Object[] {color.getRGB()};
 1272           return new Expression(color, ColorUIResource.class, "new", args);
 1273       }
 1274   }
 1275   
 1276   class MetaData {
 1277       private static final Map<String,Field> fields = Collections.synchronizedMap(new WeakHashMap<String, Field>());
 1278       private static Hashtable internalPersistenceDelegates = new Hashtable();
 1279   
 1280       private static PersistenceDelegate nullPersistenceDelegate = new NullPersistenceDelegate();
 1281       private static PersistenceDelegate enumPersistenceDelegate = new EnumPersistenceDelegate();
 1282       private static PersistenceDelegate primitivePersistenceDelegate = new PrimitivePersistenceDelegate();
 1283       private static PersistenceDelegate defaultPersistenceDelegate = new DefaultPersistenceDelegate();
 1284       private static PersistenceDelegate arrayPersistenceDelegate;
 1285       private static PersistenceDelegate proxyPersistenceDelegate;
 1286   
 1287       static {
 1288   
 1289           internalPersistenceDelegates.put("java.net.URI",
 1290                                            new PrimitivePersistenceDelegate());
 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)) {
 1331                   if (proxyPersistenceDelegate == null) {
 1332                       proxyPersistenceDelegate = new ProxyPersistenceDelegate();
 1333                   }
 1334                   return proxyPersistenceDelegate;
 1335               }
 1336           }
 1337           catch(Exception e) {}
 1338           // else if (type.getDeclaringClass() != null) {
 1339           //     return new DefaultPersistenceDelegate(new String[]{"this$0"});
 1340           // }
 1341   
 1342           String typeName = type.getName();
 1343           PersistenceDelegate pd = (PersistenceDelegate)getBeanAttribute(type, "persistenceDelegate");
 1344           if (pd == null) {
 1345               pd = (PersistenceDelegate)internalPersistenceDelegates.get(typeName);
 1346               if (pd != null) {
 1347                   return pd;
 1348               }
 1349               internalPersistenceDelegates.put(typeName, defaultPersistenceDelegate);
 1350               try {
 1351                   String name =  type.getName();
 1352                   Class c = Class.forName("java.beans." + name.replace('.', '_')
 1353                                           + "_PersistenceDelegate");
 1354                   pd = (PersistenceDelegate)c.newInstance();
 1355                   internalPersistenceDelegates.put(typeName, pd);
 1356               }
 1357               catch (ClassNotFoundException e) {
 1358                   String[] properties = getConstructorProperties(type);
 1359                   if (properties != null) {
 1360                       pd = new DefaultPersistenceDelegate(properties);
 1361                       internalPersistenceDelegates.put(typeName, pd);
 1362                   }
 1363               }
 1364               catch (Exception e) {
 1365                   System.err.println("Internal error: " + e);
 1366               }
 1367           }
 1368   
 1369           return (pd != null) ? pd : defaultPersistenceDelegate;
 1370       }
 1371   
 1372       private static String[] getConstructorProperties(Class type) {
 1373           String[] names = null;
 1374           int length = 0;
 1375           for (Constructor<?> constructor : type.getConstructors()) {
 1376               String[] value = getAnnotationValue(constructor);
 1377               if ((value != null) && (length < value.length) && isValid(constructor, value)) {
 1378                   names = value;
 1379                   length = value.length;
 1380               }
 1381           }
 1382           return names;
 1383       }
 1384   
 1385       private static String[] getAnnotationValue(Constructor<?> constructor) {
 1386           ConstructorProperties annotation = constructor.getAnnotation(ConstructorProperties.class);
 1387           return (annotation != null)
 1388                   ? annotation.value()
 1389                   : null;
 1390       }
 1391   
 1392       private static boolean isValid(Constructor<?> constructor, String[] names) {
 1393           Class[] parameters = constructor.getParameterTypes();
 1394           if (names.length != parameters.length) {
 1395               return false;
 1396           }
 1397           for (String name : names) {
 1398               if (name == null) {
 1399                   return false;
 1400               }
 1401           }
 1402           return true;
 1403       }
 1404   
 1405       private static Object getBeanAttribute(Class type, String attribute) {
 1406           try {
 1407               return Introspector.getBeanInfo(type).getBeanDescriptor().getValue(attribute);
 1408           } catch (IntrospectionException exception) {
 1409               return null;
 1410           }
 1411       }
 1412   
 1413       static Object getPrivateFieldValue(Object instance, String name) {
 1414           Field field = fields.get(name);
 1415           if (field == null) {
 1416               int index = name.lastIndexOf('.');
 1417               final String className = name.substring(0, index);
 1418               final String fieldName = name.substring(1 + index);
 1419               field = AccessController.doPrivileged(new PrivilegedAction<Field>() {
 1420                   public Field run() {
 1421                       try {
 1422                           Field field = Class.forName(className).getDeclaredField(fieldName);
 1423                           field.setAccessible(true);
 1424                           return field;
 1425                       }
 1426                       catch (ClassNotFoundException exception) {
 1427                           throw new IllegalStateException("Could not find class", exception);
 1428                       }
 1429                       catch (NoSuchFieldException exception) {
 1430                           throw new IllegalStateException("Could not find field", exception);
 1431                       }
 1432                   }
 1433               });
 1434               fields.put(name, field);
 1435           }
 1436           try {
 1437               return field.get(instance);
 1438           }
 1439           catch (IllegalAccessException exception) {
 1440               throw new IllegalStateException("Could not get value of the field", exception);
 1441           }
 1442       }
 1443   }

Save This Page
Home » openjdk-7 » java » beans » [javadoc | source]