01: package sample.evolve;
02:
03: import java.util.Hashtable;
04: import java.lang.reflect.*;
05:
06: /**
07: * Runtime system for class evolution
08: */
09: 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: } catch (ClassNotFoundException e) {
26: throw new CannotUpdateException("cannot update class: "
27: + qualifiedClassname);
28: } catch (Exception e) {
29: throw new CannotUpdateException(e);
30: }
31: }
32:
33: private static Class getUpdatedClass(String qualifiedClassname)
34: throws ClassNotFoundException {
35: int version;
36: Object found = versionNo.get(qualifiedClassname);
37: if (found == null)
38: version = 0;
39: else
40: version = ((Integer) found).intValue() + 1;
41:
42: Class c = Class.forName(qualifiedClassname + "$$" + version);
43: versionNo.put(qualifiedClassname, new Integer(version));
44: return c;
45: }
46:
47: /*
48: * initiaVersion() is used to initialize the _version field of the updatable
49: * classes.
50: */
51: public static Class initialVersion(String[] params) {
52: try {
53: return getUpdatedClass(params[0]);
54: } catch (ClassNotFoundException e) {
55: throw new RuntimeException("cannot initialize " + params[0]);
56: }
57: }
58:
59: /**
60: * make() performs the object creation of the updatable classes. The
61: * expression "new <updatable class>" is replaced with a call to this
62: * method.
63: */
64: public static Object make(Class clazz, Object[] args) {
65: Constructor[] constructors = clazz.getConstructors();
66: int n = constructors.length;
67: for (int i = 0; i < n; ++i) {
68: try {
69: return constructors[i].newInstance(args);
70: } catch (IllegalArgumentException e) {
71: // try again
72: } catch (InstantiationException e) {
73: throw new CannotCreateException(e);
74: } catch (IllegalAccessException e) {
75: throw new CannotCreateException(e);
76: } catch (InvocationTargetException e) {
77: throw new CannotCreateException(e);
78: }
79: }
80:
81: throw new CannotCreateException("no constructor matches");
82: }
83: }
|