Home | History | Annotate | Download | only in evolve
      1 package sample.evolve;
      2 
      3 import java.util.Hashtable;
      4 import java.lang.reflect.*;
      5 
      6 /**
      7  * Runtime system for class evolution
      8  */
      9 public class VersionManager {
     10     private static Hashtable versionNo = new Hashtable();
     11 
     12     public final static String latestVersionField = "_version";
     13 
     14     /**
     15      * For updating the definition of class my.X, say:
     16      *
     17      * VersionManager.update("my.X");
     18      */
     19     public static void update(String qualifiedClassname)
     20             throws CannotUpdateException {
     21         try {
     22             Class c = getUpdatedClass(qualifiedClassname);
     23             Field f = c.getField(latestVersionField);
     24             f.set(null, c);
     25         }
     26         catch (ClassNotFoundException e) {
     27             throw new CannotUpdateException("cannot update class: "
     28                     + qualifiedClassname);
     29         }
     30         catch (Exception e) {
     31             throw new CannotUpdateException(e);
     32         }
     33     }
     34 
     35     private static Class getUpdatedClass(String qualifiedClassname)
     36             throws ClassNotFoundException {
     37         int version;
     38         Object found = versionNo.get(qualifiedClassname);
     39         if (found == null)
     40             version = 0;
     41         else
     42             version = ((Integer)found).intValue() + 1;
     43 
     44         Class c = Class.forName(qualifiedClassname + "$$" + version);
     45         versionNo.put(qualifiedClassname, new Integer(version));
     46         return c;
     47     }
     48 
     49     /*
     50      * initiaVersion() is used to initialize the _version field of the updatable
     51      * classes.
     52      */
     53     public static Class initialVersion(String[] params) {
     54         try {
     55             return getUpdatedClass(params[0]);
     56         }
     57         catch (ClassNotFoundException e) {
     58             throw new RuntimeException("cannot initialize " + params[0]);
     59         }
     60     }
     61 
     62     /**
     63      * make() performs the object creation of the updatable classes. The
     64      * expression "new <updatable class>" is replaced with a call to this
     65      * method.
     66      */
     67     public static Object make(Class clazz, Object[] args) {
     68         Constructor[] constructors = clazz.getConstructors();
     69         int n = constructors.length;
     70         for (int i = 0; i < n; ++i) {
     71             try {
     72                 return constructors[i].newInstance(args);
     73             }
     74             catch (IllegalArgumentException e) {
     75                 // try again
     76             }
     77             catch (InstantiationException e) {
     78                 throw new CannotCreateException(e);
     79             }
     80             catch (IllegalAccessException e) {
     81                 throw new CannotCreateException(e);
     82             }
     83             catch (InvocationTargetException e) {
     84                 throw new CannotCreateException(e);
     85             }
     86         }
     87 
     88         throw new CannotCreateException("no constructor matches");
     89     }
     90 }
     91