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

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