Source for java.beans.DefaultPersistenceDelegate

   1: /* DefaultPersistenceDelegate.java
   2:  Copyright (C) 2005 Free Software Foundation, Inc.
   3: 
   4:  This file is part of GNU Classpath.
   5: 
   6:  GNU Classpath is free software; you can redistribute it and/or modify
   7:  it under the terms of the GNU General Public License as published by
   8:  the Free Software Foundation; either version 2, or (at your option)
   9:  any later version.
  10: 
  11:  GNU Classpath is distributed in the hope that it will be useful, but
  12:  WITHOUT ANY WARRANTY; without even the implied warranty of
  13:  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14:  General Public License for more details.
  15: 
  16:  You should have received a copy of the GNU General Public License
  17:  along with GNU Classpath; see the file COPYING.  If not, write to the
  18:  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19:  02110-1301 USA.
  20: 
  21:  Linking this library statically or dynamically with other modules is
  22:  making a combined work based on this library.  Thus, the terms and
  23:  conditions of the GNU General Public License cover the whole
  24:  combination.
  25: 
  26:  As a special exception, the copyright holders of this library give you
  27:  permission to link this library with independent modules to produce an
  28:  executable, regardless of the license terms of these independent
  29:  modules, and to copy and distribute the resulting executable under
  30:  terms of your choice, provided that you also meet, for each linked
  31:  independent module, the terms and conditions of the license of that
  32:  module.  An independent module is a module which is not derived from
  33:  or based on this library.  If you modify this library, you may extend
  34:  this exception to your version of the library, but you are not
  35:  obligated to do so.  If you do not wish to do so, delete this
  36:  exception statement from your version. */
  37: 
  38: 
  39: package java.beans;
  40: 
  41: import java.lang.reflect.InvocationTargetException;
  42: import java.lang.reflect.Method;
  43: 
  44: /** <p><code>DefaultPersistenceDelegate</code> is a {@link PersistenceDelegate}
  45:  * implementation that can be used to serialize objects which adhere to the
  46:  * Java Beans naming convention.</p>
  47:  * 
  48:  * @author Robert Schuster (robertschuster@fsfe.org)
  49:  * @since 1.4
  50:  */
  51: public class DefaultPersistenceDelegate extends PersistenceDelegate
  52: {
  53: 
  54:   private String[] constructorPropertyNames;
  55: 
  56:   /** Using this constructor the object to be serialized will be instantiated
  57:    * with the default non-argument constructor.
  58:    */
  59:   public DefaultPersistenceDelegate()
  60:   {
  61:   }
  62: 
  63:   /** This constructor allows to specify which Bean properties appear
  64:    * in the constructor.
  65:    * 
  66:    * <p>The implementation reads the mentioned properties from the Bean
  67:    * instance and applies it in the given order to a corresponding
  68:    * constructor.</p>
  69:    * 
  70:    * @param constructorPropertyNames The properties the Bean's constructor
  71:    * should be given to.
  72:    */
  73:   public DefaultPersistenceDelegate(String[] constructorPropertyNames)
  74:   {
  75:     this.constructorPropertyNames = constructorPropertyNames;
  76:   }
  77: 
  78:   protected boolean mutatesTo(Object oldInstance, Object newInstance)
  79:   {
  80:     try
  81:       {
  82: 
  83:         return (constructorPropertyNames != null
  84:                && constructorPropertyNames.length > 0
  85:                && oldInstance.getClass()
  86:                .getDeclaredMethod("equals",
  87:                                   new Class[] { Object.class }) != null)
  88:                                   ? oldInstance.equals(newInstance)
  89:                                   : super.mutatesTo(oldInstance, newInstance);
  90:       }
  91:     catch (NoSuchMethodException nsme)
  92:       {
  93:         return super.mutatesTo(oldInstance, newInstance);
  94:       }
  95:   }
  96: 
  97:   protected Expression instantiate(Object oldInstance, Encoder out)
  98:   {
  99:     Object[] args = null;
 100: 
 101:     try
 102:       {
 103:         // If there are property names in the array, then we create
 104:         // a corresponding argument array and store every
 105:         // argument in it. To retrieve an argument object we have
 106:         // dig up the right property in the bean class' BeanInfo
 107:         // object.
 108:         // This is so costly in terms of execution time I better
 109:         // not think twice about it ...
 110:         if (constructorPropertyNames != null)
 111:           {
 112:             args = new Object[constructorPropertyNames.length];
 113: 
 114:             // Look up the properties of oldInstance's class to find matches for
 115:             // the
 116:             // names given in the constructor.
 117:             PropertyDescriptor[] propertyDescs = Introspector.getBeanInfo(
 118:                                                                           oldInstance.getClass()).getPropertyDescriptors();
 119: 
 120:             for (int i = 0; i < constructorPropertyNames.length; i++)
 121:               {
 122:                 // Scan the property descriptions for a matching name.
 123:                 for (int j = 0; j < propertyDescs.length; j++)
 124:                   {
 125:                     if (propertyDescs[i].getName().equals(
 126:                                                           constructorPropertyNames[i]))
 127:                       {
 128:                         Method readMethod = propertyDescs[i].getReadMethod();
 129: 
 130:                         args[i] = readMethod.invoke(oldInstance, null);
 131:                       }
 132:                   }
 133:               }
 134:           }
 135: 
 136:       }
 137:     catch (IllegalAccessException iae)
 138:       {
 139:         out.getExceptionListener().exceptionThrown(iae);
 140:       }
 141:     catch (IllegalArgumentException iarge)
 142:       {
 143:         out.getExceptionListener().exceptionThrown(iarge);
 144:       }
 145:     catch (InvocationTargetException ite)
 146:       {
 147:         out.getExceptionListener().exceptionThrown(ite);
 148:       }
 149:     catch (IntrospectionException ie)
 150:       {
 151:         out.getExceptionListener().exceptionThrown(ie);
 152:       }
 153: 
 154:     return new Expression(oldInstance, oldInstance.getClass(), "new", args);
 155:   }
 156: 
 157:   protected void initialize(Class type, Object oldInstance, Object newInstance,
 158:                             Encoder out)
 159:   {
 160:     try
 161:       {
 162:         PropertyDescriptor[] propertyDescs = Introspector.getBeanInfo(
 163:                                                                       oldInstance.getClass()).getPropertyDescriptors();
 164: 
 165:         for (int i = 0; i < propertyDescs.length; i++)
 166:           {
 167:             Method readMethod = propertyDescs[i].getReadMethod();
 168:             Method writeMethod = propertyDescs[i].getWriteMethod();
 169: 
 170:             if (readMethod != null && writeMethod != null)
 171:               {
 172:                 Object oldValue = readMethod.invoke(oldInstance, null);
 173: 
 174:                 if (oldValue != null)
 175:                   out.writeStatement(new Statement(oldInstance,
 176:                                                    writeMethod.getName(),
 177:                                                    new Object[] { oldValue }));
 178:               }
 179:           }
 180:       }
 181:     catch (IntrospectionException ie)
 182:       {
 183:         out.getExceptionListener().exceptionThrown(ie);
 184:       }
 185:     catch (IllegalAccessException iae)
 186:       {
 187:         out.getExceptionListener().exceptionThrown(iae);
 188:       }
 189:     catch (InvocationTargetException ite)
 190:       {
 191:         out.getExceptionListener().exceptionThrown(ite);
 192:       }
 193:   }
 194: }