1 19 20 package org.openide.nodes; 21 22 import junit.framework.*; 23 import junit.textui.TestRunner; 24 import java.util.*; 25 import org.openide.cookies.EditCookie; 26 import org.openide.cookies.OpenCookie; 27 import org.openide.cookies.SaveCookie; 28 import org.openide.nodes.*; 29 30 import org.netbeans.junit.*; 31 import javax.swing.event.ChangeListener ; 32 33 import org.openide.nodes.CookieSet.Factory; 34 35 40 public class CookieSetCompatibilityTest extends NbTestCase implements java.lang.reflect.InvocationHandler { 41 private ArrayList interfaces = new ArrayList (); 42 private ArrayList classes = new ArrayList (); 43 private ArrayList instances = new ArrayList (); 44 45 public CookieSetCompatibilityTest(String name) { 46 super(name); 47 } 48 49 50 public void testRandomCheck () throws Exception { 51 long seed = System.currentTimeMillis(); 52 try { 53 compare (createOperator (new CookieSet ()), new OldCookieSetFromFebruary2005 (), seed); 54 } catch (AssertionFailedError ex) { 55 AssertionFailedError n = new AssertionFailedError ("Seed: " + seed + "\n" + ex.getMessage ()); 56 n.initCause(ex); 57 throw n; 58 } catch (Exception ex) { 59 IllegalStateException n = new IllegalStateException ("Seed: " + seed + "\n" + ex.getMessage ()); 60 n.initCause(ex); 61 throw n; 62 } 63 } 64 65 private void compare (Operator o1, Operator o2, long seed) throws Exception { 66 java.util.Random r = new java.util.Random (seed); 67 68 interfaces.add (org.openide.cookies.SaveCookie.class); 69 interfaces.add (java.io.Serializable .class); 70 interfaces.add (Runnable .class); 71 interfaces.add (Node.Cookie.class); 72 73 class L implements javax.swing.event.ChangeListener , CookieSet.Factory { 74 public int cnt; 75 76 public void stateChanged (javax.swing.event.ChangeEvent ev) { 77 cnt++; 78 } 79 80 81 private HashMap createdCookies = new HashMap (); 82 public Node.Cookie createCookie (Class c) { 83 Object o = createdCookies.get (c); 84 if (o != null) { 85 return (Node.Cookie)o; 86 } 87 88 try { 89 Node.Cookie cookie = (Node.Cookie)c.getConstructors()[0].newInstance(new Object [] { CookieSetCompatibilityTest.this }); 90 createdCookies.put (c, cookie); 91 return cookie; 92 } catch (Exception ex) { 93 throw (AssertionFailedError)new AssertionFailedError (ex.getMessage()).initCause(ex); 94 } 95 96 } 97 } 98 99 L listener1 = new L (); 100 L listener2 = new L (); 101 102 o1.addChangeListener(listener1); 103 o2.addChangeListener(listener2); 104 105 for (int bigLoop = 0; bigLoop < 1000; bigLoop++) { 106 int operation = r.nextInt(10); 107 switch (operation) { 108 case 0: { ArrayList superclasses = new ArrayList (); 110 int number = r.nextInt (interfaces.size () + 1); 111 for (int i = 0; i < number; i++) { 112 int index = r.nextInt (interfaces.size ()); 113 Class c = (Class )interfaces.get (index); 114 if (!superclasses.contains (c)) { 115 superclasses.add (c); 116 } 117 } 118 Class c = java.lang.reflect.Proxy.getProxyClass(getClass ().getClassLoader(), (Class [])superclasses.toArray(new Class [0])); 119 classes.add (c); 120 break; 121 } 122 case 1: { Object o; 124 Class c = randomClass (false, true, r); 125 if (c != null) { 126 o = c.getConstructors()[0].newInstance(new Object [] { this }); 127 } else { 128 o = new Integer (r.nextInt()); 129 } 130 instances.add (o); 131 break; 132 } 133 case 2: { if (instances.size () > 0) { 135 int index = r.nextInt (instances.size ()); 136 Object o = instances.get (index); 137 if (o instanceof Node.Cookie) { 138 o1.add ((Node.Cookie)o); 139 o2.add ((Node.Cookie)o); 140 } 141 } 142 break; 143 } 144 case 3: { if (instances.size () > 0) { 146 int index = r.nextInt (instances.size ()); 147 Object o = instances.get (index); 148 if (o instanceof Node.Cookie) { 149 o1.remove ((Node.Cookie)o); 150 o2.remove ((Node.Cookie)o); 151 } 152 } 153 break; 154 } 155 case 4: { Class query = randomClass (true, true, r); 157 Object r1 = o1.getCookie(query); 158 Object r2 = o2.getCookie(query); 159 assertSame ("After querying " + query, r1, r2); 160 break; 161 } 162 case 5: { Class c = randomClass (false, true, r); 164 if (c != null) { 165 CookieSet.Factory f = r.nextBoolean() ? listener1 : listener2; 166 167 o1.add (c, f); 168 o2.add (c, f); 169 } 170 break; 171 } 172 case 6: { Class c = randomClass (false, true, r); 174 if (c != null) { 175 CookieSet.Factory f = r.nextBoolean() ? listener1 : listener2; 176 177 o1.remove (c, f); 178 o2.remove (c, f); 179 } 180 break; 181 } 182 case 7: { Class [] arr = randomClasses (false, true, r); 184 CookieSet.Factory f = r.nextBoolean() ? listener1 : listener2; 185 186 o1.add (arr, f); 187 o2.add (arr, f); 188 break; 189 } 190 case 8: { Class [] arr = randomClasses (false, true, r); 192 CookieSet.Factory f = r.nextBoolean() ? listener1 : listener2; 193 194 o1.remove (arr, f); 195 o2.remove (arr, f); 196 break; 197 } 198 } 199 200 assertEquals ("Listener counts are the same", listener1.cnt, listener2.cnt); 201 } 202 203 } 204 205 private Class [] randomClasses (boolean fromInterfaces, boolean fromClasses, Random r) { 206 ArrayList arr = new ArrayList (); 207 int cnt = r.nextInt((fromInterfaces ? interfaces.size () : 0) + (fromClasses ? classes.size () : 0) + 1); 208 while (cnt-- > 0) { 209 Class c = randomClass (fromInterfaces, fromClasses, r); 210 if (c != null && !arr.contains (c)) { 211 arr.add (c); 212 } 213 } 214 return (Class [])arr.toArray (new Class [0]); 215 } 216 217 private Class randomClass (boolean fromInterfaces, boolean fromClasses, Random r) { 218 if (fromInterfaces && fromClasses) { 219 if (r.nextBoolean()) { 220 return randomClass (interfaces, r); 221 } else { 222 return randomClass (classes, r); 223 } 224 } 225 226 if (fromInterfaces) { 227 return randomClass (interfaces, r); 228 } 229 230 if (fromClasses) { 231 return randomClass (classes, r); 232 } 233 234 return null; 235 } 236 237 private Class randomClass (List l, Random r) { 238 if (l.size () == 0) return null; 239 240 int index = r.nextInt (l.size ()); 241 return (Class )l.get (index); 242 } 243 244 245 public interface Operator { 246 public void add (Node.Cookie cookie); 247 public void add(Class cookieClass, Factory factory); 248 public void add(Class [] cookieClass, Factory factory); 249 250 public void remove (Node.Cookie cookie); 251 public void remove(Class cookieClass, Factory factory); 252 public void remove(Class [] cookieClass, Factory factory); 253 254 public Node.Cookie getCookie (Class clazz); 255 public void addChangeListener (ChangeListener l); 256 public void removeChangeListener (ChangeListener l); 257 258 } 259 260 private Operator createOperator (final CookieSet set) { 261 class O implements Operator { 262 public void add (Node.Cookie cookie) { 263 set.add (cookie); 264 } 265 public void add(Class cookieClass, Factory factory) { 266 set.add (cookieClass, factory); 267 } 268 public void add(Class [] cookieClass, Factory factory) { 269 set.add (cookieClass, factory); 270 } 271 272 public void remove (Node.Cookie cookie) { 273 set.remove (cookie); 274 } 275 public void remove(Class cookieClass, Factory factory) { 276 set.remove (cookieClass, factory); 277 } 278 public void remove(Class [] cookieClass, Factory factory) { 279 set.remove (cookieClass, factory); 280 } 281 282 public Node.Cookie getCookie (Class clazz) { 283 return set.getCookie (clazz); 284 } 285 public void addChangeListener (ChangeListener l) { 286 set.addChangeListener (l); 287 } 288 public void removeChangeListener (ChangeListener l) { 289 set.removeChangeListener (l); 290 } 291 } 292 return new O (); 293 } 294 295 public Object invoke(Object proxy, java.lang.reflect.Method method, Object [] args) throws Throwable { 296 if (method.getDeclaringClass() == Object .class) { 297 if ("equals".equals (method.getName())) { 299 return Boolean.valueOf (proxy == args[0]); 300 } 301 if ("hashCode".equals (method.getName ())) { 302 return new Integer (System.identityHashCode(proxy)); 303 } 304 if ("toString".equals (method.getName ())) { 305 return proxy.getClass () + "@" + System.identityHashCode(proxy); 306 } 307 308 } 309 310 throw new org.openide.util.NotImplementedException ("Method: " + method); 311 } 312 313 314 315 static final class OldCookieSetFromFebruary2005 extends Object implements Operator { 316 317 private static java.lang.ThreadLocal QUERY_MODE = new java.lang.ThreadLocal (); 318 319 320 private HashMap map = new HashMap (31); 321 322 323 private javax.swing.event.EventListenerList listeners = new javax.swing.event.EventListenerList (); 324 325 326 public OldCookieSetFromFebruary2005 () {} 327 328 337 public void add (Node.Cookie cookie) { 338 synchronized (this) { 339 registerCookie (cookie.getClass (), cookie); 340 } 341 342 fireChangeEvent (); 343 } 344 345 348 public void remove (Node.Cookie cookie) { 349 synchronized (this) { 350 unregisterCookie (cookie.getClass (), cookie); 351 } 352 353 fireChangeEvent (); 354 } 355 356 361 public Node.Cookie getCookie (Class clazz) { 362 Node.Cookie ret = null; 363 synchronized (this) { 364 R r = findR (clazz); 365 if (r == null) { 366 return null; 367 } 368 ret = r.cookie (); 369 } 370 if (ret instanceof CookieEntry) { 371 if (clazz == QUERY_MODE.get ()) { 372 QUERY_MODE.set (ret); 375 ret = null; 376 } else { 377 ret = ((CookieEntry) ret).getCookie(true); 379 } 380 } 381 382 return ret; 383 } 384 385 388 public void addChangeListener (ChangeListener l) { 389 listeners.add (ChangeListener .class, l); 390 } 391 392 395 public void removeChangeListener (ChangeListener l) { 396 listeners.remove (ChangeListener .class, l); 397 } 398 399 401 static Object entryQueryMode (Class c) { 402 Object prev = QUERY_MODE.get (); 403 QUERY_MODE.set (c); 404 return prev; 405 } 406 407 409 static org.openide.util.lookup.AbstractLookup.Pair exitQueryMode (Object prev) { 410 Object cookie = QUERY_MODE.get (); 411 QUERY_MODE.set (prev); 412 if (cookie instanceof CookieEntry) { 413 return new CookieEntryPair ((CookieEntry)cookie); 414 } else { 415 return null; 416 } 417 } 418 419 421 private void fireChangeEvent () { 422 Object [] arr = listeners.getListenerList(); 423 if (arr.length > 0) { 424 javax.swing.event.ChangeEvent ev = null; 425 for (int i = arr.length-2; i>=0; i-=2) { 428 if (arr[i] == ChangeListener .class) { 429 if (ev == null) { 430 ev = new javax.swing.event.ChangeEvent (this); 431 } 432 433 ((ChangeListener )arr[i + 1]).stateChanged (ev); 434 } 435 } 436 } 437 } 438 439 445 private void registerCookie (Class c, Node.Cookie cookie) { 446 if ((c == null) || !Node.Cookie.class.isAssignableFrom(c)) return; 447 448 R r = findR (c); 449 if (r == null) { 450 r = new R (); 451 map.put (c, r); 452 } 453 454 r.add (cookie); 455 456 registerCookie (c.getSuperclass (), cookie); 457 458 Class [] inter = c.getInterfaces (); 459 for (int i = 0; i < inter.length; i++) { 460 registerCookie (inter[i], cookie); 461 } 462 } 463 464 470 private void unregisterCookie (Class c, Node.Cookie cookie) { 471 if ( 472 c == null || !Node.Cookie.class.isAssignableFrom(c) 473 ) return; 474 475 R r = findR (c); 477 if (r != null) { 478 r.remove (cookie); 480 } 481 482 unregisterCookie (c.getSuperclass (), cookie); 483 484 Class [] inter = c.getInterfaces (); 485 for (int i = 0; i < inter.length; i++) { 486 unregisterCookie (inter[i], cookie); 487 } 488 } 489 490 491 public void add(Class cookieClass, Factory factory) { 492 if (factory == null) { 493 throw new IllegalArgumentException (); 494 } 495 496 synchronized (this) { 497 registerCookie (cookieClass, new CookieEntry(factory, cookieClass)); 498 } 499 500 fireChangeEvent (); 501 } 502 503 504 public void add(Class [] cookieClass, Factory factory) { 505 if (factory == null) { 506 throw new IllegalArgumentException (); 507 } 508 509 synchronized (this) { 510 for (int i = 0; i < cookieClass.length; i++) { 511 registerCookie (cookieClass[i], new CookieEntry(factory, cookieClass[i])); 512 } 513 } 514 515 fireChangeEvent (); 516 } 517 518 522 public void remove(Class cookieClass, Factory factory) { 523 if (factory == null) { 524 throw new IllegalArgumentException (); 525 } 526 527 synchronized (this) { 528 R r = findR(cookieClass); 529 if (r != null) { 530 Node.Cookie c = r.cookie(); 531 if (c instanceof CookieEntry) { 532 CookieEntry ce = (CookieEntry)c; 533 if (ce.factory == factory) { 534 unregisterCookie (cookieClass, c); 535 } 536 } 537 } 538 } 539 540 fireChangeEvent (); 541 } 542 543 547 public void remove(Class [] cookieClass, Factory factory) { 548 if (factory == null) { 549 throw new IllegalArgumentException (); 550 } 551 552 synchronized (this) { 553 for (int i = 0; i < cookieClass.length; i++) { 554 R r = findR(cookieClass[i]); 555 if (r != null) { 556 Node.Cookie c = r.cookie(); 557 if (c instanceof CookieEntry) { 558 CookieEntry ce = (CookieEntry)c; 559 if (ce.factory == factory) { 560 unregisterCookie (cookieClass[i], c); 561 } 562 } 563 } 564 } 565 } 566 567 fireChangeEvent (); 568 } 569 570 572 private R findR (Class c) { 573 return (R)map.get (c); 574 } 575 576 580 private static Class baseForCookie (Node.Cookie c) { 581 if (c instanceof CookieEntry) { 582 return ((CookieEntry)c).klass; 583 } 584 return c.getClass (); 585 } 586 587 588 589 private static class CookieEntry implements Node.Cookie { 590 591 final Factory factory; 592 593 private final Class klass; 594 595 private java.lang.ref.Reference cookie; 596 597 598 public CookieEntry(Factory factory, Class klass) { 599 this.factory = factory; 600 this.klass = klass; 601 } 602 603 607 public synchronized Node.Cookie getCookie(boolean create) { 608 Node.Cookie ret; 609 if (create) { 610 if ((cookie == null) || ((ret = (Node.Cookie) cookie.get()) == null)) { 611 ret = factory.createCookie(klass); 612 if (ret == null) return null; 613 cookie = new java.lang.ref.WeakReference (ret); 614 } 615 } else { 616 ret = (Node.Cookie) (cookie == null ? null : cookie.get ()); 617 } 618 619 return ret; 620 } 621 } 623 625 private static final class CookieEntryPair extends org.openide.util.lookup.AbstractLookup.Pair { 626 private CookieEntry entry; 627 628 public CookieEntryPair (CookieEntry e) { 629 this.entry = e; 630 } 631 632 protected boolean creatorOf(Object obj) { 633 return obj == entry.getCookie (false); 634 } 635 636 public String getDisplayName() { 637 return getId (); 638 } 639 640 public String getId() { 641 return entry.klass.getName (); 642 } 643 644 public Object getInstance() { 645 return entry.getCookie (true); 646 } 647 648 public Class getType() { 649 return entry.klass; 650 } 651 652 protected boolean instanceOf(Class c) { 653 return c.isAssignableFrom(entry.klass); 654 } 655 656 public int hashCode () { 657 return entry.hashCode () + 5; 658 } 659 660 public boolean equals (Object obj) { 661 if (obj instanceof CookieEntryPair) { 662 return ((CookieEntryPair)obj).entry == entry; 663 } 664 return false; 665 } 666 } 668 670 private static final class R extends Object { 671 672 public List cookies; 673 674 public Class base; 675 676 R() {} 677 678 681 public void add (Node.Cookie cookie) { 682 if (cookies == null) { 683 cookies = new ArrayList (1); 684 cookies.add (cookie); 685 base = baseForCookie (cookie); 686 return; 687 } 688 689 Class newBase = baseForCookie (cookie); 690 if (base == null || newBase.isAssignableFrom (base)) { 691 cookies.set (0, cookie); 692 base = newBase; 693 } else { 694 cookies.add (cookie); 695 } 696 } 697 698 701 public boolean remove (Node.Cookie cookie) { 702 if (cookies == null) { 703 return true; 704 } 705 706 if (cookies.remove (cookie) && cookies.size () == 0) { 707 base = null; 708 cookies = null; 709 return true; 710 } 711 712 base = baseForCookie ((Node.Cookie)cookies.get (0)); 713 714 return false; 715 } 716 717 719 public Node.Cookie cookie () { 720 return cookies == null || cookies.isEmpty () ? null : (Node.Cookie)cookies.get (0); 721 } 722 } 723 } 725 } 726 | Popular Tags |