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 */ update(String qualifiedClassname)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 getUpdatedClass(String qualifiedClassname)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 */ initialVersion(String[] params)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 */ make(Class clazz, Object[] args)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