src/share/classes/java/beans/DefaultPersistenceDelegate.java

Print this page




   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 java.util.*;
  28 import java.lang.reflect.*;

  29 import sun.reflect.misc.*;
  30 
  31 
  32 /**
  33  * The <code>DefaultPersistenceDelegate</code> is a concrete implementation of
  34  * the abstract <code>PersistenceDelegate</code> class and
  35  * is the delegate used by default for classes about
  36  * which no information is available. The <code>DefaultPersistenceDelegate</code>
  37  * provides, version resilient, public API-based persistence for
  38  * classes that follow the JavaBeans&trade; conventions without any class specific
  39  * configuration.
  40  * <p>
  41  * The key assumptions are that the class has a nullary constructor
  42  * and that its state is accurately represented by matching pairs
  43  * of "setter" and "getter" methods in the order they are returned
  44  * by the Introspector.
  45  * In addition to providing code-free persistence for JavaBeans,
  46  * the <code>DefaultPersistenceDelegate</code> provides a convenient means
  47  * to effect persistent storage for classes that have a constructor
  48  * that, while not nullary, simply requires some property values


 164             }
 165         }
 166         return new Expression(oldInstance, oldInstance.getClass(), "new", constructorArgs);
 167     }
 168 
 169     private Method findMethod(Class type, String property) {
 170         if (property == null) {
 171             throw new IllegalArgumentException("Property name is null");
 172         }
 173         PropertyDescriptor pd = getPropertyDescriptor(type, property);
 174         if (pd == null) {
 175             throw new IllegalStateException("Could not find property by the name " + property);
 176         }
 177         Method method = pd.getReadMethod();
 178         if (method == null) {
 179             throw new IllegalStateException("Could not find getter for the property " + property);
 180         }
 181         return method;
 182     }
 183 
 184     private static boolean equals(Object o1, Object o2) {
 185         return (o1 == null) ? (o2 == null) : o1.equals(o2);
 186     }
 187 
 188     private void doProperty(Class type, PropertyDescriptor pd, Object oldInstance, Object newInstance, Encoder out) throws Exception {
 189         Method getter = pd.getReadMethod();
 190         Method setter = pd.getWriteMethod();
 191 
 192         if (getter != null && setter != null) {
 193             Expression oldGetExp = new Expression(oldInstance, getter.getName(), new Object[]{});
 194             Expression newGetExp = new Expression(newInstance, getter.getName(), new Object[]{});
 195             Object oldValue = oldGetExp.getValue();
 196             Object newValue = newGetExp.getValue();
 197             out.writeExpression(oldGetExp);
 198             if (!equals(newValue, out.get(oldValue))) {
 199                 // Search for a static constant with this value;
 200                 Object e = (Object[])pd.getValue("enumerationValues");
 201                 if (e instanceof Object[] && Array.getLength(e) % 3 == 0) {
 202                     Object[] a = (Object[])e;
 203                     for(int i = 0; i < a.length; i = i + 3) {
 204                         try {
 205                            Field f = type.getField((String)a[i]);
 206                            if (f.get(null).equals(oldValue)) {
 207                                out.remove(oldValue);
 208                                out.writeExpression(new Expression(oldValue, f, "get", new Object[]{null}));
 209                            }
 210                         }
 211                         catch (Exception ex) {}
 212                     }
 213                 }
 214                 invokeStatement(oldInstance, setter.getName(), new Object[]{oldValue}, out);
 215             }
 216         }
 217     }
 218 
 219     static void invokeStatement(Object instance, String methodName, Object[] args, Encoder out) {
 220         out.writeStatement(new Statement(instance, methodName, args));
 221     }
 222 
 223     // Write out the properties of this instance.
 224     private void initBean(Class type, Object oldInstance, Object newInstance, Encoder out) {
 225         for (Field field : type.getFields()) {
 226             int mod = field.getModifiers();
 227             if (Modifier.isFinal(mod) || Modifier.isStatic(mod) || Modifier.isTransient(mod)) {
 228                 continue;
 229             }
 230             try {
 231                 Expression oldGetExp = new Expression(field, "get", new Object[] { oldInstance });
 232                 Expression newGetExp = new Expression(field, "get", new Object[] { newInstance });
 233                 Object oldValue = oldGetExp.getValue();
 234                 Object newValue = newGetExp.getValue();
 235                 out.writeExpression(oldGetExp);
 236                 if (!equals(newValue, out.get(oldValue))) {
 237                     out.writeStatement(new Statement(field, "set", new Object[] { oldInstance, oldValue }));
 238                 }
 239             }
 240             catch (Exception exception) {
 241                 out.getExceptionListener().exceptionThrown(exception);
 242             }
 243         }
 244         BeanInfo info;
 245         try {
 246             info = Introspector.getBeanInfo(type);
 247         } catch (IntrospectionException exception) {
 248             return;
 249         }
 250         // Properties
 251         for (PropertyDescriptor d : info.getPropertyDescriptors()) {
 252             if (d.isTransient()) {
 253                 continue;
 254             }
 255             try {
 256                 doProperty(type, d, oldInstance, newInstance, out);




   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 java.util.*;
  28 import java.lang.reflect.*;
  29 import java.util.Objects;
  30 import sun.reflect.misc.*;
  31 
  32 
  33 /**
  34  * The <code>DefaultPersistenceDelegate</code> is a concrete implementation of
  35  * the abstract <code>PersistenceDelegate</code> class and
  36  * is the delegate used by default for classes about
  37  * which no information is available. The <code>DefaultPersistenceDelegate</code>
  38  * provides, version resilient, public API-based persistence for
  39  * classes that follow the JavaBeans&trade; conventions without any class specific
  40  * configuration.
  41  * <p>
  42  * The key assumptions are that the class has a nullary constructor
  43  * and that its state is accurately represented by matching pairs
  44  * of "setter" and "getter" methods in the order they are returned
  45  * by the Introspector.
  46  * In addition to providing code-free persistence for JavaBeans,
  47  * the <code>DefaultPersistenceDelegate</code> provides a convenient means
  48  * to effect persistent storage for classes that have a constructor
  49  * that, while not nullary, simply requires some property values


 165             }
 166         }
 167         return new Expression(oldInstance, oldInstance.getClass(), "new", constructorArgs);
 168     }
 169 
 170     private Method findMethod(Class type, String property) {
 171         if (property == null) {
 172             throw new IllegalArgumentException("Property name is null");
 173         }
 174         PropertyDescriptor pd = getPropertyDescriptor(type, property);
 175         if (pd == null) {
 176             throw new IllegalStateException("Could not find property by the name " + property);
 177         }
 178         Method method = pd.getReadMethod();
 179         if (method == null) {
 180             throw new IllegalStateException("Could not find getter for the property " + property);
 181         }
 182         return method;
 183     }
 184 




 185     private void doProperty(Class type, PropertyDescriptor pd, Object oldInstance, Object newInstance, Encoder out) throws Exception {
 186         Method getter = pd.getReadMethod();
 187         Method setter = pd.getWriteMethod();
 188 
 189         if (getter != null && setter != null) {
 190             Expression oldGetExp = new Expression(oldInstance, getter.getName(), new Object[]{});
 191             Expression newGetExp = new Expression(newInstance, getter.getName(), new Object[]{});
 192             Object oldValue = oldGetExp.getValue();
 193             Object newValue = newGetExp.getValue();
 194             out.writeExpression(oldGetExp);
 195             if (!Objects.equals(newValue, out.get(oldValue))) {
 196                 // Search for a static constant with this value;
 197                 Object e = (Object[])pd.getValue("enumerationValues");
 198                 if (e instanceof Object[] && Array.getLength(e) % 3 == 0) {
 199                     Object[] a = (Object[])e;
 200                     for(int i = 0; i < a.length; i = i + 3) {
 201                         try {
 202                            Field f = type.getField((String)a[i]);
 203                            if (f.get(null).equals(oldValue)) {
 204                                out.remove(oldValue);
 205                                out.writeExpression(new Expression(oldValue, f, "get", new Object[]{null}));
 206                            }
 207                         }
 208                         catch (Exception ex) {}
 209                     }
 210                 }
 211                 invokeStatement(oldInstance, setter.getName(), new Object[]{oldValue}, out);
 212             }
 213         }
 214     }
 215 
 216     static void invokeStatement(Object instance, String methodName, Object[] args, Encoder out) {
 217         out.writeStatement(new Statement(instance, methodName, args));
 218     }
 219 
 220     // Write out the properties of this instance.
 221     private void initBean(Class type, Object oldInstance, Object newInstance, Encoder out) {
 222         for (Field field : type.getFields()) {
 223             int mod = field.getModifiers();
 224             if (Modifier.isFinal(mod) || Modifier.isStatic(mod) || Modifier.isTransient(mod)) {
 225                 continue;
 226             }
 227             try {
 228                 Expression oldGetExp = new Expression(field, "get", new Object[] { oldInstance });
 229                 Expression newGetExp = new Expression(field, "get", new Object[] { newInstance });
 230                 Object oldValue = oldGetExp.getValue();
 231                 Object newValue = newGetExp.getValue();
 232                 out.writeExpression(oldGetExp);
 233                 if (!Objects.equals(newValue, out.get(oldValue))) {
 234                     out.writeStatement(new Statement(field, "set", new Object[] { oldInstance, oldValue }));
 235                 }
 236             }
 237             catch (Exception exception) {
 238                 out.getExceptionListener().exceptionThrown(exception);
 239             }
 240         }
 241         BeanInfo info;
 242         try {
 243             info = Introspector.getBeanInfo(type);
 244         } catch (IntrospectionException exception) {
 245             return;
 246         }
 247         // Properties
 248         for (PropertyDescriptor d : info.getPropertyDescriptors()) {
 249             if (d.isTransient()) {
 250                 continue;
 251             }
 252             try {
 253                 doProperty(type, d, oldInstance, newInstance, out);