1 package test.javassist.convert; 2 3 import java.util.HashMap; 4 import java.util.Map; 5 6 import javassist.ClassPool; 7 import javassist.CodeConverter; 8 import javassist.CtClass; 9 import junit.framework.TestCase; 10 11 public class ArrayAccessReplaceTest extends TestCase { 12 private static SimpleInterface simple = null; 13 setUp()14 public void setUp() throws Exception { 15 ClassPool pool = new ClassPool(true); 16 CtClass echoClass = pool.get(ArrayAccessReplaceTest.class.getName() + "$Echo"); 17 CtClass simpleClass = pool.get(ArrayAccessReplaceTest.class.getName() + "$Simple"); 18 CodeConverter converter = new CodeConverter(); 19 converter.replaceArrayAccess(echoClass, new CodeConverter.DefaultArrayAccessReplacementMethodNames()); 20 simpleClass.instrument(converter); 21 //simpleClass.writeFile("/tmp"); 22 23 simple = (SimpleInterface)new javassist.Loader.Simple().invokeDefineClass(simpleClass) 24 .getConstructor().newInstance(); 25 } 26 testComplex()27 public void testComplex() throws Exception { 28 ClassPool pool = new ClassPool(true); 29 CtClass clazz = pool.get(ArrayAccessReplaceTest.class.getName() + "$Complex"); 30 31 CodeConverter converter = new CodeConverter(); 32 converter.replaceArrayAccess(clazz, new CodeConverter.DefaultArrayAccessReplacementMethodNames()); 33 clazz.instrument(converter); 34 ComplexInterface instance 35 = (ComplexInterface)new javassist.Loader.Simple().invokeDefineClass(clazz) 36 .getConstructor().newInstance(); 37 assertEquals(Integer.valueOf(5), instance.complexRead(4)); 38 } 39 testBoolean()40 public void testBoolean() throws Exception { 41 for (int i = 0; i < 100; i++) { 42 boolean value = i % 5 == 0; 43 simple.setBoolean(i, value); 44 } 45 46 for (int i = 0; i < 100; i++) { 47 boolean value = i % 5 == 0; 48 assertEquals(value, simple.getBoolean(i)); 49 } 50 } 51 testByte()52 public void testByte() throws Exception { 53 for (byte i = 0; i < 100; i++) { 54 simple.setByte(i, i); 55 } 56 57 for (byte i = 0; i < 100; i++) { 58 assertEquals(i, simple.getByte(i)); 59 } 60 } 61 testShort()62 public void testShort() throws Exception { 63 for (short i = 0; i < 100; i++) { 64 simple.setShort(i, i); 65 } 66 67 for (short i = 0; i < 100; i++) { 68 assertEquals(i, simple.getShort(i)); 69 } 70 } 71 testChar()72 public void testChar() throws Exception { 73 for (char i = 0; i < 100; i++) { 74 simple.setChar(i, i); 75 } 76 77 for (char i = 0; i < 100; i++) { 78 assertEquals(i, simple.getChar(i)); 79 } 80 } 81 testInt()82 public void testInt() throws Exception { 83 for (int i = 0; i < 100; i++) { 84 simple.setInt(i, i); 85 } 86 87 for (int i = 0; i < 100; i++) { 88 assertEquals(i, simple.getInt(i)); 89 } 90 } 91 testLong()92 public void testLong() throws Exception { 93 for (int i = 0; i < 100; i++) { 94 simple.setLong(i, i); 95 } 96 97 for (int i = 0; i < 100; i++) { 98 assertEquals(i, simple.getLong(i)); 99 } 100 } 101 testFloat()102 public void testFloat() throws Exception { 103 for (int i = 0; i < 100; i++) { 104 simple.setFloat(i, i); 105 } 106 107 for (int i = 0; i < 100; i++) { 108 assertEquals((float)i, simple.getFloat(i), 0); 109 } 110 } 111 testDouble()112 public void testDouble() throws Exception { 113 for (int i = 0; i < 100; i++) { 114 simple.setDouble(i, i); 115 } 116 117 for (int i = 0; i < 100; i++) { 118 assertEquals((double)i, simple.getDouble(i), 0); 119 } 120 } 121 testObject()122 public void testObject() throws Exception { 123 for (int i = 0; i < 100; i++) { 124 simple.setObject(i, Integer.valueOf(i)); 125 } 126 127 for (int i = 0; i < 100; i++) { 128 assertEquals(Integer.valueOf(i), simple.getObject(i)); 129 } 130 } 131 testFoo()132 public void testFoo() throws Exception { 133 for (int i = 0; i < 100; i++) { 134 simple.setFoo(i, new Foo(i)); 135 } 136 137 for (int i = 0; i < 100; i++) { 138 assertEquals(new Foo(i), simple.getFoo(i)); 139 } 140 } 141 testMulti()142 public void testMulti() throws Exception { 143 for (int i = 2; i < 100; i++) { 144 simple.setMultiFoo(0, 1, i, new Foo(i)); 145 } 146 147 for (int i = 2; i < 100; i++) { 148 assertEquals(new Foo(i), simple.getMultiFoo(0, 1, i)); 149 } 150 } 151 152 @SuppressWarnings({"rawtypes","unchecked"}) 153 public static class Echo { 154 public static Map byteMap = new HashMap(); 155 public static Map charMap = new HashMap(); 156 public static Map doubleMap = new HashMap(); 157 public static Map floatMap = new HashMap(); 158 public static Map intMap = new HashMap(); 159 public static Map longMap = new HashMap(); 160 public static Map objectMap = new HashMap(); 161 public static Map shortMap = new HashMap(); 162 arrayReadObject(Object array, int index)163 public static Object arrayReadObject(Object array, int index) { 164 return objectMap.get(Integer.valueOf(index)); 165 } 166 arrayWriteObject(Object array, int index, Object element)167 public static void arrayWriteObject(Object array, int index, Object element) { 168 objectMap.put(Integer.valueOf(index), element); 169 } 170 arrayReadByteOrBoolean(Object array, int index)171 public static byte arrayReadByteOrBoolean(Object array, int index) { 172 return ((Byte)byteMap.get(Integer.valueOf(index))).byteValue(); 173 } 174 arrayWriteByteOrBoolean(Object array, int index, byte element)175 public static void arrayWriteByteOrBoolean(Object array, int index, byte element) { 176 byteMap.put(Integer.valueOf(index), Byte.valueOf(element)); 177 } 178 arrayReadChar(Object array, int index)179 public static char arrayReadChar(Object array, int index) { 180 return ((Character)charMap.get(Integer.valueOf(index))).charValue(); 181 } 182 arrayWriteChar(Object array, int index, char element)183 public static void arrayWriteChar(Object array, int index, char element) { 184 charMap.put(Integer.valueOf(index), Character.valueOf(element)); 185 } 186 arrayReadDouble(Object array, int index)187 public static double arrayReadDouble(Object array, int index) { 188 return ((Double)doubleMap.get(Integer.valueOf(index))).doubleValue(); 189 } 190 arrayWriteDouble(Object array, int index, double element)191 public static void arrayWriteDouble(Object array, int index, double element) { 192 doubleMap.put(Integer.valueOf(index), Double.valueOf(element)); 193 } 194 arrayReadFloat(Object array, int index)195 public static float arrayReadFloat(Object array, int index) { 196 return ((Float)floatMap.get(Integer.valueOf(index))).floatValue(); 197 } 198 arrayWriteFloat(Object array, int index, float element)199 public static void arrayWriteFloat(Object array, int index, float element) { 200 floatMap.put(Integer.valueOf(index), Float.valueOf(element)); 201 } 202 arrayReadInt(Object array, int index)203 public static int arrayReadInt(Object array, int index) { 204 return ((Integer)intMap.get(Integer.valueOf(index))).intValue(); 205 } 206 arrayWriteInt(Object array, int index, int element)207 public static void arrayWriteInt(Object array, int index, int element) { 208 intMap.put(Integer.valueOf(index), Integer.valueOf(element)); 209 } 210 arrayReadLong(Object array, int index)211 public static long arrayReadLong(Object array, int index) { 212 return ((Long)longMap.get(Integer.valueOf(index))).longValue(); 213 } 214 arrayWriteLong(Object array, int index, long element)215 public static void arrayWriteLong(Object array, int index, long element) { 216 longMap.put(Integer.valueOf(index), Long.valueOf(element)); 217 } 218 arrayReadShort(Object array, int index)219 public static short arrayReadShort(Object array, int index) { 220 return ((Short)shortMap.get(Integer.valueOf(index))).shortValue(); 221 } 222 arrayWriteShort(Object array, int index, short element)223 public static void arrayWriteShort(Object array, int index, short element) { 224 shortMap.put(Integer.valueOf(index), Short.valueOf(element)); 225 } 226 } 227 228 public static class Foo { 229 public int bar; 230 Foo(int bar)231 public Foo(int bar) { 232 this.bar = bar; 233 } 234 hashCode()235 public int hashCode() { 236 return bar; 237 } 238 equals(Object o)239 public boolean equals(Object o) { 240 if (! (o instanceof Foo)) 241 return false; 242 243 return ((Foo)o).bar == bar; 244 } 245 } 246 247 public static interface SimpleInterface { setBoolean(int pos, boolean value)248 public void setBoolean(int pos, boolean value); getBoolean(int pos)249 public boolean getBoolean(int pos); 250 setByte(int pos, byte value)251 public void setByte(int pos, byte value); getByte(int pos)252 public byte getByte(int pos); 253 setShort(int pos, short value)254 public void setShort(int pos, short value); getShort(int pos)255 public short getShort(int pos); 256 setChar(int pos, char value)257 public void setChar(int pos, char value); getChar(int pos)258 public char getChar(int pos); 259 setInt(int pos, int value)260 public void setInt(int pos, int value); getInt(int pos)261 public int getInt(int pos); 262 setLong(int pos, long value)263 public void setLong(int pos, long value); getLong(int pos)264 public long getLong(int pos); 265 setFloat(int pos, float value)266 public void setFloat(int pos, float value); getFloat(int pos)267 public float getFloat(int pos); 268 setDouble(int pos, double value)269 public void setDouble(int pos, double value); getDouble(int pos)270 public double getDouble(int pos); 271 setObject(int pos, Object value)272 public void setObject(int pos, Object value); getObject(int pos)273 public Object getObject(int pos); 274 setFoo(int pos, Foo value)275 public void setFoo(int pos, Foo value); getFoo(int pos)276 public Foo getFoo(int pos); 277 setMultiFoo(int one, int two, int three, Foo foo)278 public void setMultiFoo(int one, int two, int three, Foo foo); getMultiFoo(int one, int two, int three)279 public Foo getMultiFoo(int one, int two, int three); 280 } 281 282 public static class Simple implements SimpleInterface { 283 private boolean[] booleans; 284 private byte[] bytes; 285 private short[] shorts; 286 private char[] chars; 287 private int[] ints; 288 private long[] longs; 289 private float[] floats; 290 private double[] doubles; 291 private Object[] objects; 292 private Foo[] foos; 293 private Foo[][][] multi; 294 Simple()295 public Simple() { 296 multi[0] = new Foo[0][0]; 297 multi[0][1] = new Foo[0]; 298 } 299 getBoolean(int pos)300 public boolean getBoolean(int pos) { 301 return booleans[pos]; 302 } 303 getByte(int pos)304 public byte getByte(int pos) { 305 return bytes[pos]; 306 } 307 getChar(int pos)308 public char getChar(int pos) { 309 return chars[pos]; 310 } 311 getDouble(int pos)312 public double getDouble(int pos) { 313 return doubles[pos]; 314 } 315 getFloat(int pos)316 public float getFloat(int pos) { 317 return floats[pos]; 318 } 319 getFoo(int pos)320 public Foo getFoo(int pos) { 321 return foos[pos]; 322 } 323 getInt(int pos)324 public int getInt(int pos) { 325 return ints[pos]; 326 } 327 getLong(int pos)328 public long getLong(int pos) { 329 return longs[pos]; 330 } 331 getObject(int pos)332 public Object getObject(int pos) { 333 return objects[pos]; 334 } 335 getShort(int pos)336 public short getShort(int pos) { 337 return shorts[pos]; 338 } 339 getMultiFoo(int one, int two, int three)340 public Foo getMultiFoo(int one, int two, int three) { 341 return multi[one][two][three]; 342 } 343 setBoolean(int pos, boolean value)344 public void setBoolean(int pos, boolean value) { 345 booleans[pos] = value; 346 } 347 setByte(int pos, byte value)348 public void setByte(int pos, byte value) { 349 bytes[pos] = value; 350 } 351 setChar(int pos, char value)352 public void setChar(int pos, char value) { 353 chars[pos] = value; 354 } 355 setDouble(int pos, double value)356 public void setDouble(int pos, double value) { 357 doubles[pos] = value; 358 } 359 setFloat(int pos, float value)360 public void setFloat(int pos, float value) { 361 floats[pos] = value; 362 } 363 setFoo(int pos, Foo value)364 public void setFoo(int pos, Foo value) { 365 foos[pos] = value; 366 } 367 setInt(int pos, int value)368 public void setInt(int pos, int value) { 369 ints[pos] = value; 370 } 371 setLong(int pos, long value)372 public void setLong(int pos, long value) { 373 longs[pos] = value; 374 } 375 setObject(int pos, Object value)376 public void setObject(int pos, Object value) { 377 objects[pos] = value; 378 } 379 setShort(int pos, short value)380 public void setShort(int pos, short value) { 381 shorts[pos] = value; 382 } 383 setMultiFoo(int one, int two, int three, Foo foo)384 public void setMultiFoo(int one, int two, int three, Foo foo) { 385 multi[one][two][three] = foo; 386 } 387 } 388 389 public static interface ComplexInterface { complexRead(int x)390 public Number complexRead(int x); 391 } 392 393 public static class Complex implements ComplexInterface { 394 private Integer[] nums; 395 private Long[] longNums; 396 private static Integer justRead; 397 arrayReadObject(Object array, int offset)398 public static Object arrayReadObject(Object array, int offset) { 399 return Integer.valueOf(justRead.intValue() + offset); 400 } 401 arrayWriteObject(Object array, int offset, Object element)402 public static void arrayWriteObject(Object array, int offset, Object element) { 403 justRead = (Integer) element; 404 } 405 getInteger(int i)406 public Object getInteger(int i) { 407 return (Object) Integer.valueOf(i); 408 } 409 complexRead(int x)410 public Number complexRead(int x) { 411 Number[] ns = null; 412 Number n1, n2, n3, n4; 413 try { 414 ((Object[])ns)[1] = getInteger(x); 415 // We have to throw an error since we can't intercept 416 // a guaranteed null array read yet (likely never will be able to) 417 throw new Error("hi"); 418 } catch (Error error) { 419 ns = nums; 420 } catch (Exception exception) { 421 ns = longNums; 422 } finally { 423 n1 = ns[1]; 424 n2 = ns[2]; 425 n3 = ns[3]; 426 n4 = ns[4]; 427 428 n2.intValue(); 429 n3.intValue(); 430 n4.intValue(); 431 } 432 433 return n1; 434 } 435 } 436 }