1 package sample.evolve; 2 3 import javassist.*; 4 import java.io.IOException ; 5 6 26 public class Evolution implements Translator { 27 public final static String handlerMethod = "_makeInstance"; 28 public final static String latestVersionField 29 = VersionManager.latestVersionField; 30 public final static String versionManagerMethod = "initialVersion"; 31 32 private static CtMethod trapMethod; 33 private static final int initialVersion = 0; 34 private ClassPool pool; 35 private String updatableClassName = null; 36 private CtClass updatableClass = null; 37 38 public void start(ClassPool _pool) throws NotFoundException { 39 pool = _pool; 40 41 trapMethod = _pool.getMethod("sample.evolve.Sample", "make"); 44 } 45 46 public void onLoad(ClassPool _pool, String classname) 47 throws NotFoundException, CannotCompileException 48 { 49 onLoadUpdatable(classname); 50 51 55 CtClass clazz = _pool.get(classname); 56 CtClass absClass = updatableClass; 57 CodeConverter converter = new CodeConverter(); 58 converter.replaceNew(absClass, absClass, handlerMethod); 59 clazz.instrument(converter); 60 } 61 62 private void onLoadUpdatable(String classname) 63 throws NotFoundException, CannotCompileException 64 { 65 68 int i = classname.lastIndexOf('$'); 69 if (i <= 0) 70 return; 71 72 String orgname = classname.substring(0, i); 73 if (!orgname.equals(updatableClassName)) 74 return; 75 76 int version; 77 try { 78 version = Integer.parseInt(classname.substring(i + 1)); 79 } 80 catch (NumberFormatException e) { 81 throw new NotFoundException(classname, e); 82 } 83 84 CtClass clazz = pool.getAndRename(orgname, classname); 85 makeConcreteClass(clazz, updatableClass, version); 86 } 87 88 90 public void makeUpdatable(String classname) 91 throws NotFoundException, CannotCompileException 92 { 93 if (pool == null) 94 throw new RuntimeException ( 95 "Evolution has not been linked to ClassPool."); 96 97 CtClass c = pool.get(classname); 98 updatableClassName = classname; 99 updatableClass = makeAbstractClass(c); 100 } 101 102 105 protected CtClass makeAbstractClass(CtClass clazz) 106 throws CannotCompileException, NotFoundException 107 { 108 int i; 109 110 CtClass absClass = pool.makeClass(clazz.getName()); 111 absClass.setModifiers(Modifier.PUBLIC | Modifier.ABSTRACT); 112 absClass.setSuperclass(clazz.getSuperclass()); 113 absClass.setInterfaces(clazz.getInterfaces()); 114 115 117 CtField fld = new CtField(pool.get("java.lang.Class"), 118 latestVersionField, absClass); 119 fld.setModifiers(Modifier.PUBLIC | Modifier.STATIC); 120 121 CtField.Initializer finit 122 = CtField.Initializer.byCall( 123 pool.get("sample.evolve.VersionManager"), 124 versionManagerMethod, 125 new String [] { clazz.getName() }); 126 absClass.addField(fld, finit); 127 128 CtField[] fs = clazz.getDeclaredFields(); 129 for (i = 0; i < fs.length; ++i) { 130 CtField f = fs[i]; 131 if (Modifier.isPublic(f.getModifiers())) 132 absClass.addField(new CtField(f.getType(), f.getName(), 133 absClass)); 134 } 135 136 CtConstructor[] cs = clazz.getDeclaredConstructors(); 137 for (i = 0; i < cs.length; ++i) { 138 CtConstructor c = cs[i]; 139 int mod = c.getModifiers(); 140 if (Modifier.isPublic(mod)) { 141 CtMethod wm 142 = CtNewMethod.wrapped(absClass, handlerMethod, 143 c.getParameterTypes(), 144 c.getExceptionTypes(), 145 trapMethod, null, absClass); 146 wm.setModifiers(Modifier.PUBLIC | Modifier.STATIC); 147 absClass.addMethod(wm); 148 } 149 } 150 151 CtMethod[] ms = clazz.getDeclaredMethods(); 152 for (i = 0; i < ms.length; ++i) { 153 CtMethod m = ms[i]; 154 int mod = m.getModifiers(); 155 if (Modifier.isPublic(mod)) 156 if (Modifier.isStatic(mod)) 157 throw new CannotCompileException( 158 "static methods are not supported."); 159 else { 160 CtMethod m2 161 = CtNewMethod.abstractMethod(m.getReturnType(), 162 m.getName(), 163 m.getParameterTypes(), 164 m.getExceptionTypes(), 165 absClass); 166 absClass.addMethod(m2); 167 } 168 } 169 170 return absClass; 171 } 172 173 180 protected void makeConcreteClass(CtClass clazz, 181 CtClass abstractClass, int version) 182 throws CannotCompileException, NotFoundException 183 { 184 int i; 185 clazz.setSuperclass(abstractClass); 186 CodeConverter converter = new CodeConverter(); 187 CtField[] fs = clazz.getDeclaredFields(); 188 for (i = 0; i < fs.length; ++i) { 189 CtField f = fs[i]; 190 if (Modifier.isPublic(f.getModifiers())) 191 converter.redirectFieldAccess(f, abstractClass, f.getName()); 192 } 193 194 CtConstructor[] cs = clazz.getDeclaredConstructors(); 195 for (i = 0; i < cs.length; ++i) 196 cs[i].instrument(converter); 197 198 CtMethod[] ms = clazz.getDeclaredMethods(); 199 for (i = 0; i < ms.length; ++i) 200 ms[i].instrument(converter); 201 } 202 } 203 | Popular Tags |