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