home *** CD-ROM | disk | FTP | other *** search
/ Internet News 1999 October / INEWS_10_CD.ISO / pc / jdk / jdk1.2.2 / docs / guide / serialization / examples / altimpl / EvolvedClass.java next >
Encoding:
Java Source  |  1999-09-19  |  9.0 KB  |  264 lines

  1. /*
  2.  *
  3.  * @(#)EvolvedClass.java    1.7 98/10/01        
  4.  *
  5.  * Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
  6.  *
  7.  * This software is the confidential and proprietary information of Sun
  8.  * Microsystems, Inc. ("Confidential Information").  You shall not
  9.  * disclose such Confidential Information and shall use it only in
  10.  * accordance with the terms of the license agreement you entered into
  11.  * with Sun.
  12.  *
  13.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
  14.  * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  15.  * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  16.  * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
  17.  * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
  18.  * THIS SOFTWARE OR ITS DERIVATIVES.
  19.  *
  20.  * 
  21.  */
  22.  
  23. import java.io.*;
  24. import java.awt.*;
  25.  
  26. /**
  27.  *
  28.  * This example shows how to use the Serializable Fields API with 
  29.  * Serialization, demonstrating that the class can define fields 
  30.  * other than those already in the class to be serializable. This 
  31.  * differs from just rewriting the writeObject method to customize 
  32.  * the data format (see the Custom Data Format example) because, 
  33.  * in this example, versioning support still holds.
  34.  *
  35.  * Using the Serializable Fields API, this example specifically 
  36.  * changes the internal representation of a rectangle from 
  37.  * x1,y1,x2,y2 implementation (see Original Class) to Point(x1,y1), 
  38.  * Point(x2,y2) (see Evolved Class) while the external representation 
  39.  * still remains x1, y1, x2, y2. This ensures bidirectional compatibility 
  40.  * between the original and evolved representations. 
  41.  *
  42.  * The original rectangle class (in OriginalClass.java) consists of four 
  43.  * integers (x1, y1, x2, y2). Instead of four integers, the evolved rectangle 
  44.  * class (in this file) has two Points as fields.  In order for this  
  45.  * evolved class to fulfill its contract with the original class, the 
  46.  * evolved class saves its fields as four integers (x1, y1, x2, y2) 
  47.  * instead of two points.  By doing this the evolved class ensures 
  48.  * bidirectional compatibility with the original class.
  49.  *
  50.  * To see how to run this: see OriginalClass.java
  51.  *
  52.  *  Compiled and Tested with JDK1.2
  53.  */
  54.  
  55. public class EvolvedClass {
  56.  
  57.     /** 
  58.      *  There are two options: either a user can serialize an object or
  59.      *  deserialize it. (using the -s or -d flag). These options allow
  60.      *  for the demonstration of bidirection readability and writeability
  61.      *  between the original and the evolved class. In other words,
  62.      *  one can serialize an object here and deserialize it with the evolved
  63.      *  class or vice versa.
  64.      */
  65.     public static void main(String args[]) {
  66.  
  67.         ARectangle orgClass = new ARectangle(100, 100, 102, 102);
  68.         ARectangle newClass = null;
  69.  
  70.         boolean serialize = false;
  71.         boolean deserialize = false;
  72.  
  73.         /* 
  74.      * see if we are serializing or deserializing.
  75.          * The ability to deserialize or serialize allows
  76.          * us to see the bidirectional readability and writeability
  77.          */
  78.         if (args.length == 1) {
  79.             if (args[0].equals("-d")) {
  80.         deserialize = true;
  81.             } else if (args[0].equals("-s")) {
  82.                 serialize = true;
  83.             } else {
  84.                 usage();
  85.                 System.exit(0);
  86.             }
  87.         } else {
  88.             usage();
  89.             System.exit(0);
  90.         }
  91.  
  92.         /* 
  93.      * Serialize the original class if that's the option chosen
  94.          */
  95.         if (serialize) {
  96.             try {
  97.                 FileOutputStream fo = new FileOutputStream("evolve.tmp");
  98.                 ObjectOutputStream so = new ObjectOutputStream(fo);
  99.                 so.writeObject(orgClass);
  100.                 so.flush();
  101.             } catch (Exception e) {
  102.                 System.out.println(e);
  103.                 System.exit(1);
  104.         }
  105.         }
  106.  
  107.         /* 
  108.      * Deserialize, if that's the option chosen and print the name
  109.          * of the object, which will allow us to see who serialized the
  110.          * object, the original class or the evolved class file
  111.          */
  112.         if (deserialize) {
  113.             try {
  114.                 FileInputStream fi = new FileInputStream("evolve.tmp");
  115.                 ObjectInputStream si = new ObjectInputStream(fi);
  116.                 newClass = (ARectangle) si.readObject();
  117.             } catch (Exception e) {
  118.                 System.out.println(e);
  119.                 System.exit(1);
  120.             }
  121.             System.out.println("Now printing deserialized object: ");
  122.             System.out.println();
  123.         System.out.println(newClass);
  124.         }
  125.     }
  126.     
  127.     /** 
  128.      * Prints out the usage
  129.      */
  130.     static void usage() {
  131.         System.out.println("Usage:");
  132.         System.out.println("      -s (in order to serialize)");
  133.         System.out.println("      -d (in order to deserialize)");
  134.     }
  135. }
  136.  
  137. /**
  138.  * The evolved Rectangle Class. Interally consists of two fields of type
  139.  * Point but externally is still 4 integers (so that it is compatible
  140.  * with the original rectangle class) 
  141.  *
  142.  * In order to make this possible, we need to use the Serializable
  143.  * Field API so that we can define serializable fields that are 
  144.  * not part of the implementation class.
  145.  */
  146. class ARectangle implements java.io.Serializable {
  147.  
  148.     // new rectangle representation
  149.     
  150.     /**
  151.      * First of two points forming diagonal of rectangle.
  152.      *
  153.      * Note that this field is not a default serializable field
  154.      * due to the use of serialPersistentFields member within this class.
  155.      */
  156.     Point point1;
  157.  
  158.  
  159.     /**
  160.      * Second of two points forming diagonal of rectangle.
  161.      *
  162.      * Note that this field is not a default serializable field
  163.      * due to the use of serialPersistentFields member within this class.
  164.      */
  165.     Point point2;
  166.  
  167.     /* 
  168.      * mandatory SUID field for an evolved Serializable class.
  169.      * serialVersionUID is gotten by doing the serialver command
  170.      * on the original class:
  171.      *                  serialver ARectangle (the original rectangle) 
  172.      */ 
  173.     static final long serialVersionUID = 9030593813711490592L;
  174.  
  175.  
  176.     /**
  177.      * The special member, serialPeristentFields, explicitly declares 
  178.      * Serializable fields for this class. This allows for fields other
  179.      * than the fields in the class to be persistent. Since we want to 
  180.      * save the state of the two Points point1 and point2, we declare 
  181.      * the 4 ints as the serial persistent fields
  182.      * 
  183.      * @serialField x1    Integer 
  184.      *              X-coordinate of point 1 of diagonal points of rectangle.
  185.      * @serialField y1    Integer 
  186.      *              Y-coordinate of point 1 of diagonal points of rectangle.
  187.      * @serialField x2    Integer 
  188.      *              X-coordinate of point 2 of diagonal points of rectangle.
  189.      * @serialField y2    Integer 
  190.      *              Y-coordinate of point 2 of diagonal points of rectangle.
  191.      */
  192.     private static final ObjectStreamField[] serialPersistentFields = { 
  193.     new ObjectStreamField("x1", Integer.TYPE), 
  194.     new ObjectStreamField("y1", Integer.TYPE), 
  195.     new ObjectStreamField("x2", Integer.TYPE), 
  196.     new ObjectStreamField("y2", Integer.TYPE) 
  197.     }; 
  198.     
  199.     ARectangle(int x1, int y1, int x2, int y2) {
  200.     point1 = new Point(x1, y1);
  201.     point2 = new Point(x2, y2);
  202.     }
  203.  
  204.     /**
  205.      * writeObject - Writes out the serializable fields 
  206.      * (the 4 integers, x1, y1, x2, y2) using the 
  207.      * Serializable Field API. (the methods putFields and
  208.      * writeFields of the ObjectOutputStream Class and the method put
  209.      * of the ObjectOutputStream.PutField inner class)
  210.      * 
  211.      * @serialData Only the serializable fields of the class are written.
  212.      *             No optional data written. 
  213.      */
  214.     private void writeObject(ObjectOutputStream s)
  215.     throws IOException {
  216.         
  217.         // set the values of the Serializable fields
  218.         ObjectOutputStream.PutField fields = s.putFields();
  219.         fields.put("x1", point1.x);
  220.         fields.put("y1", point1.y);
  221.         fields.put("x2", point2.x);
  222.         fields.put("y2", point2.y);
  223.         
  224.         // save them
  225.         s.writeFields();        
  226.   }
  227.  
  228.     /**
  229.      * readsObject - Reads in the serializable fields 
  230.      * (the 4 integers, x1, y1, x2, y2) using the 
  231.      * Serializable Field API. (the methods getFields and
  232.      * readFields of the ObjectInputStream Class and the method get
  233.      * of the ObjectOutputStream.GetField inner class)
  234.      *
  235.      * @serialData No optional data is read.
  236.      */
  237.     private void readObject(ObjectInputStream s)
  238.     throws IOException {
  239.  
  240.         // prepare to read the alternate persistent fields
  241.         ObjectInputStream.GetField fields = null;
  242.         try { 
  243.         fields = s.readFields();
  244.         } catch (Exception ClassNotFoundException) {
  245.         throw new IOException();
  246.         }
  247.         
  248.         // read the alternate persistent fields
  249.         int x1 = (int)fields.get("x1", 0);
  250.         int y1 = (int)fields.get("y1", 0);
  251.         int x2 = (int)fields.get("x2", 0);
  252.         int y2 = (int)fields.get("y2", 0);
  253.      
  254.         // save them back as Points.
  255.         point1 = new Point(x1, y1);
  256.         point2 = new Point(x2, y2);
  257.     }
  258.  
  259.     public String toString() {
  260.     return("point1.x: " + point1.x + "\npoint1.y: " + point1.y + "\npoint2.x: " + point2.x + "\npoint2.y: " + point2.y);
  261.     }
  262. }
  263.  
  264.