Warnings.
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4 * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
6 * The contents of this file are subject to the terms of either the GNU
7 * General Public License Version 2 only ("GPL") or the Common
8 * Development and Distribution License("CDDL") (collectively, the
9 * "License"). You may not use this file except in compliance with the
10 * License. You can obtain a copy of the License at
11 * http://www.netbeans.org/cddl-gplv2.html
12 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13 * specific language governing permissions and limitations under the
14 * License. When distributing the software, include this License Header
15 * Notice in each file and include the License file at
16 * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
17 * particular file as subject to the "Classpath" exception as provided
18 * by Sun in the GPL Version 2 section of the License file that
19 * accompanied this code. If applicable, add the following below the
20 * License Header, with the fields enclosed by brackets [] replaced by
21 * your own identifying information:
22 * "Portions Copyrighted [year] [name of copyright owner]"
26 * The Original Software is NetBeans. The Initial Developer of the Original
27 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28 * Microsystems, Inc. All Rights Reserved.
30 * If you wish your version of this file to be governed by only the CDDL
31 * or only the GPL Version 2, indicate your decision by adding
32 * "[Contributor] elects to include this software in this distribution
33 * under the [CDDL or GPL Version 2] license." If you do not indicate a
34 * single choice of license, a recipient has the option to distribute
35 * your version of this file under either the CDDL, the GPL Version 2 or
36 * to extend the choice of license to its licensees as provided above.
37 * However, if you add GPL Version 2 code and therefore, elected the GPL
38 * Version 2 license, then the option applies only if the new code is
39 * made subject to such option by the copyright holder.
42 package org.openide.util.lookup;
44 import java.io.ByteArrayInputStream;
45 import java.io.ByteArrayOutputStream;
46 import java.io.ObjectInputStream;
47 import java.io.ObjectOutputStream;
48 import java.io.Serializable;
49 import java.lang.ref.WeakReference;
50 import java.lang.ref.Reference;
51 import java.util.ArrayList;
52 import java.util.Arrays;
53 import java.util.Collection;
54 import java.util.Collections;
55 import java.util.Iterator;
56 import java.util.LinkedList;
57 import java.util.List;
58 import java.util.concurrent.Executors;
59 import java.util.concurrent.TimeUnit;
60 import javax.swing.ActionMap;
61 import javax.swing.InputMap;
62 import org.netbeans.junit.NbTestCase;
63 import org.openide.util.Lookup;
64 import org.openide.util.Lookup.Template;
65 import org.openide.util.LookupEvent;
66 import org.openide.util.LookupListener;
68 @SuppressWarnings("unchecked") // XXX ought to be corrected, just a lot of them
69 public class AbstractLookupBaseHid extends NbTestCase {
70 private static AbstractLookupBaseHid running;
72 /** instance content to work with */
74 /** the lookup to work on */
75 protected Lookup instanceLookup;
76 /** the lookup created to work with */
77 private Lookup lookup;
78 /** implementation of methods that can influence the behaviour */
81 protected AbstractLookupBaseHid(String testName, Impl impl) {
83 if (impl == null && (this instanceof Impl)) {
89 protected @Override void setUp() {
90 this.ic = new InstanceContent ();
92 beforeActualTest(getName());
94 this.instanceLookup = createInstancesLookup (ic);
95 this.lookup = createLookup (instanceLookup);
99 protected @Override void tearDown() {
103 /** The methods to influence test behaviour */
104 public static interface Impl {
105 /** Creates the initial abstract lookup.
107 public Lookup createInstancesLookup (InstanceContent ic);
108 /** Creates an lookup for given lookup. This class just returns
109 * the object passed in, but subclasses can be different.
110 * @param lookup in lookup
111 * @return a lookup to use
113 public Lookup createLookup (Lookup lookup);
115 /** If the impl has any caches that would prevent the system
116 * to not garbage collect correctly, then clear them now.
118 public void clearCaches ();
121 private Lookup createInstancesLookup (InstanceContent ic) {
122 return impl.createInstancesLookup (ic);
125 private Lookup createLookup (Lookup lookup) {
126 return impl.createLookup (lookup);
129 /** instances that we register */
130 private static Object[] INSTANCES = new Object[] {
135 /** Test if first is really first.
137 public void testFirst () {
144 Integer found = lookup.lookup(Integer.class);
146 fail ("First object is not first: " + found + " != " + i1);
149 List<Integer> list = new ArrayList<Integer>();
154 found = lookup.lookup (Integer.class);
156 fail ("Second object is not first after reorder: " + found + " != " + i2);
161 public void testToString() {
162 String txt = lookup.toString();
163 assertNotNull("Something is there", txt);
164 assertTrue("Something2: " + txt, txt.length() > 0);
168 /** Tests ordering of items in the lookup.
170 public void testOrder () {
171 addInstances (INSTANCES);
173 if (INSTANCES[0] != lookup.lookup (INSTANCES[0].getClass ())) {
174 fail ("First object in intances not found");
177 Iterator<?> all = lookup.lookupAll(Object.class).iterator();
178 checkIterator ("Difference between instances added and found", all, Arrays.asList (INSTANCES));
181 /** Checks the reorder of items in lookup reflects the result.
182 * Testing both classes and interfaces, because they are often treated
185 public void testReorder () {
188 Runnable r1 = new Runnable () {
189 public void run () {}
191 Runnable r2 = new Runnable () {
192 public void run () {}
194 List<Object> l = new ArrayList<Object>();
202 assertEquals ("s1 is found", s1, lookup.lookup (String.class));
203 assertEquals ("r1 is found", r1, lookup.lookup (Runnable.class));
205 Collections.reverse (l);
209 assertEquals ("s2 is found", s2, lookup.lookup (String.class));
210 assertEquals ("r2 is found", r2, lookup.lookup (Runnable.class));
213 /** Tries to set empty collection to the lookup.
215 public void testSetEmpty () {
216 ic.add ("A serializable string");
217 lookup.lookup (Serializable.class);
219 ic.set (Collections.emptyList(), null);
222 /** Tests a more complex reorder on nodes.
224 public void testComplexReorder () {
228 List<Object> l = new ArrayList<Object>();
233 assertEquals ("Find integer", i1, lookup.lookup (Integer.class));
234 assertEquals ("Find long", i2, lookup.lookup (Long.class));
235 assertEquals ("Find number", i1, lookup.lookup (Number.class));
237 Collections.reverse (l);
241 assertEquals ("Find integer", i1, lookup.lookup (Integer.class));
242 assertEquals ("Find long", i2, lookup.lookup (Long.class));
243 assertEquals ("Find number", i2, lookup.lookup (Number.class));
246 /** Checks whether setPairs keeps the order.
248 public void testSetPairs () {
249 // test setPairs method
250 List<Object> li = new ArrayList<Object>();
251 li.addAll (Arrays.asList (INSTANCES));
254 Lookup.Result<Object> res = lookup.lookupResult(Object.class);
255 Iterator<?> all = res.allInstances().iterator();
256 checkIterator ("Original order not kept", all, li);
259 Collections.reverse (li);
262 LL listener = new LL (res);
263 res.addLookupListener (listener);
265 if (listener.getCount () != 1) {
266 fail ("Result has not changed even we set reversed order");
269 all = res.allInstances ().iterator ();
270 checkIterator ("Reversed order not kept", all, li);
273 /** Checks whether setPairs fires correct events.
275 public void testSetPairsFire () {
276 // test setPairs method
277 List<Object> li = new ArrayList<Object>();
278 li.addAll (Arrays.asList (INSTANCES));
281 Lookup.Result<Integer> res = lookup.lookupResult(Integer.class);
282 Iterator<?> all = res.allInstances().iterator();
283 checkIterator ("Integer is not there", all, Collections.nCopies (1, INSTANCES[0]));
286 LL listener = new LL (res);
287 res.addLookupListener (listener);
289 List<Object> l2 = new ArrayList<Object>(li);
290 l2.remove (INSTANCES[0]);
293 all = lookup.lookupAll(Object.class).iterator();
294 checkIterator ("The removed integer is not noticed", all, l2);
296 if (listener.getCount () != 1) {
297 fail ("Nothing has not been fired");
301 /** Checks whether set pairs does not fire when they should not.
303 public void testSetPairsDoesNotFire () {
304 Object tmp = new Object ();
306 List<Object> li = new ArrayList<Object>();
308 li.addAll (Arrays.asList (INSTANCES));
311 Lookup.Result<Integer> res = lookup.lookupResult(Integer.class);
312 Iterator<?> all = res.allInstances ().iterator ();
313 checkIterator ("Integer is not there", all, Collections.nCopies (1, INSTANCES[0]));
316 LL listener = new LL (res);
317 res.addLookupListener (listener);
319 List<Object> l2 = new ArrayList<Object>(li);
323 all = lookup.lookupAll(Object.class).iterator();
324 checkIterator ("The removed integer is not noticed", all, l2);
326 if (listener.getCount () != 0) {
327 fail ("Something has been fired");
331 /** Test whether after registration it is possible to find registered objects
334 public void testLookupAndAdd () throws Exception {
335 addInstances (INSTANCES);
337 for (int i = 0; i < INSTANCES.length; i++) {
338 Object obj = INSTANCES[i];
339 findAll (lookup, obj.getClass (), true);
343 /** Tries to find all classes and superclasses in the lookup.
345 private void findAll(Lookup lookup, Class<?> clazz, boolean shouldBeThere) {
346 if (clazz == null) return;
348 Object found = lookup.lookup (clazz);
351 // should find at either instance or something else, but must
352 // find at least something
353 fail ("Lookup (" + clazz.getName () + ") found nothing");
356 if (!shouldBeThere) {
357 // should find at either instance or something else, but must
358 // find at least something
359 fail ("Lookup (" + clazz.getName () + ") found " + found);
363 Lookup.Result<?> res = lookup.lookupResult(clazz);
364 Collection<?> collection = res.allInstances();
366 for (int i = 0; i < INSTANCES.length; i++) {
367 boolean isSubclass = clazz.isInstance (INSTANCES[i]);
368 boolean isThere = collection.contains (INSTANCES[i]);
370 if (isSubclass != isThere) {
372 // should find at either instance or something else, but must
373 // find at least something
374 fail ("Lookup.Result (" + clazz.getName () + ") for " + INSTANCES[i] + " is subclass: " + isSubclass + " isThere: " + isThere);
378 // go on for superclasses
380 findAll (lookup, clazz.getSuperclass (), shouldBeThere);
382 Class[] ies = clazz.getInterfaces ();
383 for (int i = 0; i < ies.length; i++) {
384 findAll (lookup, ies[i], shouldBeThere);
388 /** Test if it is possible to remove a registered object. */
389 public void testRemoveRegisteredObject() {
390 Integer inst = new Integer(10);
393 if (lookup.lookup(inst.getClass()) == null) {
394 // should find an instance
395 fail("Lookup (" + inst.getClass().getName () + ") found nothing");
399 if (lookup.lookup(inst.getClass()) != null) {
400 // should NOT find an instance
401 fail("Lookup (" + inst.getClass().getName () +
402 ") found an instance after remove operation");
406 public void testCanReturnReallyStrangeResults () throws Exception {
407 class QueryingPair extends AbstractLookup.Pair<Object> {
408 private Integer i = 434;
414 public void doTest () throws Exception {
418 Object found = lookup.lookup (QueryingPair.class);
419 assertEquals ("This object is found", this, found);
424 // Implementation of pair
427 public String getId() {
428 return getType ().toString();
431 public String getDisplayName() {
435 public Class<?> getType() {
439 protected boolean creatorOf(Object obj) {
443 protected boolean instanceOf(Class<?> c) {
444 assertEquals ("Integer found or exception is thrown", i, lookup.lookup (Integer.class));
445 return c.isAssignableFrom(getType ());
448 public Object getInstance() {
456 QueryingPair qp = new QueryingPair ();
460 /** Test of firing events. */
461 public void testLookupListener() {
463 Lookup.Result<?> res = lookup.lookupResult(inst.getClass());
466 LL listener = new LL(res);
467 res.addLookupListener(listener);
470 if (listener.getCount() == 0) {
471 fail("None event fired during NbLookup.addPair()");
475 if (listener.getCount() == 0) {
476 fail("None event fired during NbLookup.removePair()");
480 if (listener.getCount() == 0) {
481 fail("None event fired during second NbLookup.addPair()");
485 if (listener.getCount() == 0) {
486 fail("None event fired during second NbLookup.removePair()");
490 /** Testing identity of the lookup.
492 public void testId () {
493 Lookup.Template<?> templ;
496 addInstances (INSTANCES);
498 Lookup.Result<?> res = lookup.lookupResult(Object.class);
499 for (AbstractLookup.Item<?> item : res.allItems()) {
501 templ = new Lookup.Template<Object>(null, item.getId(), null);
502 cnt = lookup.lookup (templ).allInstances ().size ();
504 fail ("Identity lookup failed. Instances = " + cnt);
507 templ = makeTemplate(item.getType(), item.getId());
508 cnt = lookup.lookup (templ).allInstances ().size ();
510 fail ("Identity lookup with type failed. Instances = " + cnt);
513 templ = makeTemplate(this.getClass(), item.getId());
514 cnt = lookup.lookup (templ).allInstances ().size ();
516 fail ("Identity lookup with wrong type failed. Instances = " + cnt);
519 templ = new Lookup.Template<Object>(null, null, item.getInstance());
520 cnt = lookup.lookup (templ).allInstances ().size ();
522 fail ("Instance lookup failed. Instances = " + cnt);
525 templ = new Lookup.Template<Object>(null, item.getId(), item.getInstance());
526 cnt = lookup.lookup (templ).allInstances ().size ();
528 fail ("Instance & identity lookup failed. Instances = " + cnt);
533 private static <T> Lookup.Template<T> makeTemplate(Class<T> clazz, String id) { // captures type parameter
534 return new Lookup.Template<T>(clazz, id, null);
537 /** Tests adding and removing.
539 public void testAddAndRemove () throws Exception {
540 Object map = new javax.swing.ActionMap ();
543 Lookup.Result<?> res = lookup.lookupResult(map.getClass());
545 res.addLookupListener (ll);
550 assertEquals ("First change when adding", ll.getCount (), 1);
554 assertEquals ("Second when removing", ll.getCount (), 1);
558 assertEquals ("Third when readding", ll.getCount (), 1);
562 assertEquals ("Forth when reremoving", ll.getCount (), 1);
566 /** Will a class garbage collect even it is registered in lookup.
568 public void testGarbageCollect () throws Exception {
569 ClassLoader l = new CL ();
570 Class<?> c = l.loadClass(Garbage.class.getName());
571 Reference<?> ref = new WeakReference<Object>(c);
575 // now test garbage collection
579 assertGC ("The classloader has not been garbage collected!", ref);
582 /** Items are the same as results.
584 public void testItemsAndIntances () {
585 addInstances (INSTANCES);
587 Lookup.Result<Object> r = lookup.lookupResult(Object.class);
588 Collection<? extends Lookup.Item<?>> items = r.allItems();
589 Collection<?> insts = r.allInstances();
591 if (items.size () != insts.size ()) {
592 fail ("Different size of sets");
595 for (Lookup.Item<?> item : items) {
596 if (!insts.contains (item.getInstance ())) {
597 fail ("Intance " + item.getInstance () + " is missing in " + insts);
602 /** Checks search for interface.
604 public void testSearchForInterface () {
605 Lookup.Template<Serializable> t = new Lookup.Template<Serializable>(Serializable.class, null, null);
607 assertNull("Nothing to find", lookup.lookupItem (t));
609 Serializable s = new Serializable () {};
612 Lookup.Item item = lookup.lookupItem (t);
613 assertNotNull ("Something found", item);
616 /** Test to add broken item if it incorrectly answers instanceOf questions.
618 public void testIncorectInstanceOf40364 () {
619 final Long sharedLong = new Long (0);
621 class P extends AbstractLookup.Pair<Object> {
622 public boolean isLong;
628 protected boolean creatorOf (Object obj) {
629 return obj == sharedLong;
632 public String getDisplayName () {
636 public String getId () {
640 public Object getInstance () {
644 public Class<?> getType() {
645 return isLong ? Long.class : Number.class;
648 protected boolean instanceOf(Class<?> c) {
649 return c.isAssignableFrom (getType ());
652 public @Override int hashCode() {
653 return getClass ().hashCode ();
656 public @Override boolean equals(Object obj) {
657 return obj != null && getClass ().equals (obj.getClass ());
661 // to create the right structure in the lookup
662 lookup.lookup (Object.class);
663 lookup.lookup (Long.class);
664 lookup.lookup (Number.class);
666 P lng1 = new P (true);
669 P lng2 = new P (false);
670 ic.setPairs (Collections.singleton (lng2));
672 Collection<? extends Lookup.Item<?>> res = lookup.lookupResult(Object.class).allItems();
673 assertEquals ("Just one pair", 1, res.size ());
676 public void testAbsolutelyCrazyWayToSimulateIssue48590ByChangingTheBehaviourOfEqualOnTheFly () throws Exception {
677 class X implements TestInterfaceInheritanceA, TestInterfaceInheritanceB {
679 final X shared = new X ();
681 class P extends AbstractLookup.Pair<Object> {
688 protected boolean creatorOf (Object obj) {
689 return obj == shared;
692 public String getDisplayName () {
696 public String getId () {
700 public Object getInstance () {
704 public Class<?> getType() {
705 return howLong == 0 ? TestInterfaceInheritanceB.class : TestInterfaceInheritanceA.class;
708 protected boolean instanceOf(Class<?> c) {
709 return c.isAssignableFrom (getType ());
712 public @Override int hashCode() {
713 return getClass ().hashCode ();
716 public @Override boolean equals(Object obj) {
717 if (obj instanceof P) {
719 if (this.howLong > 0) {
727 return getClass ().equals (p.getClass ());
733 // to create the right structure in the lookup
734 Lookup.Result<?> a = lookup.lookupResult(TestInterfaceInheritanceA.class);
735 Lookup.Result<?> b = lookup.lookupResult(TestInterfaceInheritanceB.class);
740 assertEquals ("One in a", 1, a.allItems ().size ());
741 assertEquals ("One in b", 1, b.allItems ().size ());
746 /* Following call used to generate this exception:
747 java.lang.IllegalStateException: Duplicate pair in treePair1: pair2: index1: 0 index2: 0 item1: org.openide.util.lookup.AbstractLookupBaseHid$1X@1a457b6 item2: org.openide.util.lookup.AbstractLookupBaseHid$1X@1a457b6 id1: 7a78d3 id2: 929206
748 at org.openide.util.lookup.ALPairComparator.compare(ALPairComparator.java:52)
749 at java.util.Arrays.mergeSort(Arrays.java:1284)
750 at java.util.Arrays.sort(Arrays.java:1223)
751 at java.util.Collections.sort(Collections.java:159)
752 at org.openide.util.lookup.InheritanceTree.retainAllInterface(InheritanceTree.java:753)
753 at org.openide.util.lookup.InheritanceTree.retainAll(InheritanceTree.java:183)
754 at org.openide.util.lookup.DelegatingStorage.retainAll(DelegatingStorage.java:83)
755 at org.openide.util.lookup.AbstractLookup.setPairsAndCollectListeners(AbstractLookup.java:238)
756 at org.openide.util.lookup.AbstractLookup.setPairs(AbstractLookup.java:203)
757 at org.openide.util.lookup.AbstractLookup$Content.setPairs(AbstractLookup.java:885)
758 at org.openide.util.lookup.AbstractLookupBaseHid.testAbsolutelyCrazyWayToSimulateIssue48590ByChangingTheBehaviourOfEqualOnTheFly(AbstractLookupBaseHid.java:696)
759 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
760 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
761 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
762 at org.netbeans.junit.NbTestCase.run(NbTestCase.java:119)
764 ic.setPairs (Collections.singleton (lng2));
769 public void testInstancesArePreservedFoundWhenFixing48590 () throws Exception {
770 class X implements Runnable, Serializable {
775 public void assertOnlyMe (String msg, Lookup.Result<?> res) {
776 Collection<?> col = res.allInstances();
777 assertEquals (msg + " just one", 1, col.size ());
778 assertSame (msg + " and it is me", this, col.iterator ().next ());
782 Lookup.Result<?> runnable = lookup.lookupResult(Runnable.class);
783 Lookup.Result<?> serial = lookup.lookupResult(Serializable.class);
790 x.assertOnlyMe ("x implements it (1)", runnable);
791 x.assertOnlyMe ("x implements it (2)", serial);
793 ic.set (Collections.singleton (x), null);
795 x.assertOnlyMe ("x implements it (3)", runnable);
796 x.assertOnlyMe ("x implements it (4)", serial);
799 /** Testing lookup of inherited classes. */
800 public void testInheritance() {
802 class B extends A implements java.rmi.Remote {}
803 class BB extends B {}
804 class C extends A implements java.rmi.Remote {}
807 A[] types = {new B(), new BB(), new C(), new D()};
809 for (int i = 0; i < types.length; i++) {
811 if (lookup.lookup(types[i].getClass()) == null) {
812 // should find an instance
813 fail("Lookup (" + types[i].getClass().getName () + ") found nothing");
820 size1 = lookup.lookupAll(java.rmi.Remote.class).size();
821 size2 = countInstances(types, java.rmi.Remote.class);
823 if (size1 != size2) fail("Lookup with interface failed: " + size1 + " != " + size2);
826 size1 = lookup.lookupAll(A.class).size();
827 size2 = countInstances(types, A.class);
829 if (size1 != size2) fail("Lookup with superclass failed: " + size1 + " != " + size2);
832 /** Test interface inheritance.
834 public void testInterfaceInheritance() {
835 TestInterfaceInheritanceA[] types = {
836 new TestInterfaceInheritanceB() {},
837 new TestInterfaceInheritanceBB() {},
838 new TestInterfaceInheritanceC() {},
839 new TestInterfaceInheritanceD() {}
842 for (int i = 0; i < types.length; i++) {
844 if (lookup.lookup(types[i].getClass()) == null) {
845 // should find an instance
846 fail("Lookup (" + types[i].getClass().getName () + ") found nothing");
854 Lookup.Result<?> res = lookup.lookupResult(java.rmi.Remote.class);
856 size1 = res.allInstances().size();
857 size2 = countInstances(types, java.rmi.Remote.class);
859 if (size1 != size2) fail("Lookup with interface failed: " + size1 + " != " + size2);
862 size1 = lookup.lookupAll(TestInterfaceInheritanceA.class).size();
863 size2 = countInstances(types, TestInterfaceInheritanceA.class);
865 if (size1 != size2) fail("Lookup with superclass failed: " + size1 + " != " + size2);
867 res.addLookupListener (l);
868 ic.remove (types[0]);
870 if (l.getCount () != 1) {
871 fail ("No notification that a Remote is removed");
875 /** Checks whether the AbstractLookup is guarded against modifications
876 * while doing some kind of modification.
878 public void testModificationArePreventedWhenDoingModifications () throws Exception {
879 BrokenPair broken = new BrokenPair (true, false);
882 Lookup.Template<BrokenPair> templ = new Lookup.Template<BrokenPair>(BrokenPair.class);
883 Lookup.Item<BrokenPair> item = lookup.lookupItem (templ);
884 assertEquals ("Broken is found", broken, item);
887 public void testModificationArePreventedWhenDoingModificationsResult () throws Exception {
888 BrokenPair broken = new BrokenPair (false, true);
891 Lookup.Template<BrokenPair> templ = new Lookup.Template<BrokenPair>(BrokenPair.class);
893 Collection<? extends BrokenPair> c = lookup.lookup (templ).allInstances();
894 assertEquals ("One item", 1, c.size ());
895 assertEquals ("Broken is found again", broken, c.iterator().next ());
898 public void testModificationArePreventedWhenDoingModificationsItemAndResult () throws Exception {
899 BrokenPair broken = new BrokenPair (false, true);
902 Lookup.Template<BrokenPair> templ = new Lookup.Template<BrokenPair>(BrokenPair.class);
903 Lookup.Item<BrokenPair> item = lookup.lookupItem (templ);
904 assertEquals ("Broken is found", broken, item);
906 Collection<? extends BrokenPair> c = lookup.lookup(templ).allInstances();
907 assertEquals ("One item", 1, c.size ());
908 assertEquals ("Broken is found again", broken, c.iterator().next ());
911 public void testModificationArePreventedWhenDoingModificationsResultAndItem () throws Exception {
912 BrokenPair broken = new BrokenPair (false, true);
915 Lookup.Template<BrokenPair> templ = new Lookup.Template<BrokenPair>(BrokenPair.class);
916 Collection<? extends BrokenPair> c = lookup.lookup(templ).allInstances();
917 assertEquals ("One item", 1, c.size ());
918 assertEquals ("Broken is found again", broken, c.iterator().next ());
920 Object item = lookup.lookupItem (templ);
921 assertEquals ("Broken is found", broken, item);
924 public void testAddALotOfPairsIntoTheLookupOneByOne () throws Exception {
925 Lookup.Result<Integer> res = lookup.lookupResult(Integer.class);
926 for (int i = 0; i < 1000; i++) {
930 "there is the right count",
932 res.allItems().size ()
936 public void testAddALotOfPairsIntoTheLookup () throws Exception {
937 List<Integer> arr = new ArrayList<Integer>();
938 for (int i = 0; i < 1000; i++) {
944 "there is the right count",
946 lookup.lookupResult(Integer.class).allItems().size()
951 public void testDoubleAddIssue35274 () throws Exception {
952 class P extends AbstractLookup.Pair<Object> {
953 protected boolean creatorOf(Object obj) { return false; }
954 public String getDisplayName() { return ""; }
955 public String getId() { return ""; }
956 public Object getInstance() { return null; }
957 public Class<?> getType() { return Object.class; }
958 protected boolean instanceOf(Class<?> c) { return c.isAssignableFrom(getType ()); }
959 public @Override int hashCode() {return getClass().hashCode();}
960 public @Override boolean equals(Object obj) {return getClass() == obj.getClass();}
968 Lookup.Result<Object> result = lookup.lookupResult(Object.class);
969 Collection res = result.allItems ();
970 assertEquals ("One item there", 1, res.size ());
971 assertTrue ("It is the p", p == res.iterator ().next ());
976 Reference<?> ref = new WeakReference<Object>(result);
978 assertGC ("The result can disappear", ref);
982 result = lookup.lookupResult(Object.class);
983 res = result.allItems ();
984 assertEquals ("One item is still there", 1, res.size ());
985 assertTrue ("But the p2 replaced p", p2 == res.iterator ().next ());
989 /** Test for proper serialization.
991 public void testSerializationSupport () throws Exception {
992 doSerializationSupport (1);
994 public void testDoubleSerializationSupport () throws Exception {
995 doSerializationSupport (2);
998 private void doSerializationSupport (int count) throws Exception {
999 if (lookup instanceof Serializable) {
1000 ic.addPair (new SerialPair ("1"));
1001 ic.addPair (new SerialPair ("2"));
1002 ic.addPair (new SerialPair ("3"));
1004 Lookup l = (Lookup)reserialize(lookup);
1006 assertEquals ("Able to answer simple query", "1", l.lookup (String.class));
1008 assertEquals ("Three objects there", 3, l.lookup (new Lookup.Template (String.class)).allInstances().size ());
1010 while (count-- > 0) {
1011 l = (Lookup)reserialize(l);
1014 assertEquals ("Able to answer simple query", "1", l.lookup (String.class));
1016 assertEquals ("Three objects there", 3, l.lookup (new Lookup.Template (String.class)).allInstances().size ());
1020 /** When a lookup with two different versions of the same class
1021 * get's serialized, the results may be very bad.
1023 public void testSerializationOfTwoClassesWithTheSameName () throws Exception {
1024 if (lookup instanceof Serializable) {
1025 doTwoSerializedClasses (false, false);
1028 public void testSerializationOfTwoClassesWithTheSameNameButQueryBeforeSave () throws Exception {
1029 if (lookup instanceof Serializable) {
1030 doTwoSerializedClasses (true, false);
1033 public void testSerializationOfTwoClassesWithTheSameNameWithBroken () throws Exception {
1034 if (lookup instanceof Serializable) {
1035 doTwoSerializedClasses (false, true);
1038 public void testSerializationOfTwoClassesWithTheSameNameButQueryBeforeSaveWithBroken () throws Exception {
1039 if (lookup instanceof Serializable) {
1040 doTwoSerializedClasses (true, true);
1044 private void doTwoSerializedClasses (boolean queryBeforeSerialization, boolean useBroken) throws Exception {
1045 ClassLoader loader = new CL ();
1046 Class c = loader.loadClass (Garbage.class.getName ());
1048 // in case of InheritanceTree it creates a slot for class Garbage
1051 // but creates new instance and adds it into the lookup
1052 // without querying for it
1054 c = loader.loadClass (Garbage.class.getName ());
1056 Object theInstance = c.newInstance ();
1058 ic.addPair (new SerialPair (theInstance));
1060 Broken2Pair broken = null;
1062 broken = new Broken2Pair ();
1063 ic.addPair (broken);
1066 "We need to create the slot for the List as " +
1067 "the Broken2Pair will ask for it after deserialization",
1068 lookup.lookup (java.awt.List.class)
1072 if (queryBeforeSerialization) {
1073 assertEquals ("Instance is found", theInstance, lookup.lookup (c));
1076 // replace the old lookup with new one
1077 lookup = (Lookup)reserialize(lookup);
1079 Lookup.Result result = lookup.lookup (new Lookup.Template (Garbage.class));
1080 assertEquals ("One item is the result", 1, result.allInstances ().size ());
1081 Object r = result.allInstances ().iterator ().next ();
1082 assertNotNull("A value is found", r);
1083 assertEquals ("It is of the right class", Garbage.class, r.getClass());
1086 /** Test of reorder and item change which used to fail on interfaces.
1088 public void testReoderingIssue13779 () throws Exception {
1089 LinkedList arr = new LinkedList ();
1091 class R extends Exception implements Cloneable {
1093 Object o1 = new R ();
1094 Object o2 = new R ();
1095 Object o3 = new R ();
1102 Lookup.Result objectResult = lookup.lookup (new Lookup.Template (Exception.class));
1103 Lookup.Result interfaceResult = lookup.lookup (new Lookup.Template (Cloneable.class));
1104 objectResult.allItems ();
1105 interfaceResult.allItems ();
1107 LL l1 = new LL (objectResult);
1108 LL l2 = new LL (interfaceResult);
1110 objectResult.addLookupListener(l1);
1111 interfaceResult.addLookupListener(l2);
1117 assertEquals ("One change on objects", 1, l1.getCount ());
1118 assertEquals ("One change on interfaces", 1, l2.getCount ());
1120 arr.addFirst (new Cloneable () { });
1123 assertEquals ("No change on objects", 0, l1.getCount ());
1124 assertEquals ("But one change on interfaces", 1, l2.getCount ());
1128 public void testDeadlockBetweenProxyResultAndLookupIssue47772 () throws Exception {
1129 final String myModule = "My Module";
1132 class MyProxy extends ProxyLookup {
1134 super (new Lookup[] { lookup });
1137 final MyProxy my = new MyProxy ();
1139 final Lookup.Result allModules = my.lookup (new Lookup.Template (String.class));
1141 class PairThatNeedsInfoAboutModules extends AbstractLookup.Pair {
1142 public String getDisplayName () {
1143 return "Need a module";
1145 public String getId () {
1146 return getDisplayName ();
1148 public Class getType () {
1149 return Integer.class;
1151 protected boolean instanceOf (Class c) {
1152 if (c == Integer.class) {
1153 synchronized (this) {
1157 } catch (InterruptedException ex) {
1158 fail (ex.getMessage ());
1161 java.util.Collection coll = allModules.allInstances ();
1162 assertEquals ("Size is 1", 1, coll.size ());
1163 assertEquals ("My module is there", myModule, coll.iterator ().next ());
1165 return c.isAssignableFrom (Integer.class);
1168 public Object getInstance () {
1169 return new Integer (10);
1172 protected boolean creatorOf (Object obj) {
1173 return new Integer (10).equals (obj);
1177 PairThatNeedsInfoAboutModules pair = new PairThatNeedsInfoAboutModules ();
1180 synchronized (pair) {
1181 class BlockInInstanceOf implements Runnable {
1182 public void run () {
1183 Integer i = my.lookup(Integer.class);
1184 assertEquals (new Integer (10), i);
1187 BlockInInstanceOf blk = new BlockInInstanceOf ();
1188 Executors.newSingleThreadScheduledExecutor().schedule(blk, 0, TimeUnit.MICROSECONDS);
1192 java.util.Collection coll = allModules.allInstances ();
1193 assertEquals ("Size is 1", 1, coll.size ());
1194 assertEquals ("My module is there", myModule, coll.iterator ().next ());
1197 public void testAWayToGenerateProblem13779 () {
1198 ic.add (new Integer (1));
1199 ic.add (new Integer (2));
1200 ic.add (new Integer (1));
1201 ic.add (new Integer (2));
1203 Collection c = lookup.lookup (new Lookup.Template (Integer.class)).allInstances ();
1204 assertEquals ("There are two objects", 2, c.size ());
1208 /** Replacing items with different objects.
1210 public void testReplacingObjectsDoesNotGenerateException () throws Exception {
1211 LinkedList arr = new LinkedList ();
1213 class R extends Exception implements Cloneable {
1228 public void testAfterDeserializationNoQueryIsPeformedOnAlreadyQueriedObjects() throws Exception {
1229 if (! (lookup instanceof Serializable)) {
1230 // well this test works only for serializable lookups
1234 SerialPair my = new SerialPair ("no");
1237 Lookup.Result res = lookup.lookup (new Lookup.Template (String.class));
1238 assertEquals ("One instance", 1, res.allInstances().size ());
1239 assertEquals ("my.instanceOf called once", 1, my.countInstanceOf);
1241 Lookup serial = (Lookup)reserialize(lookup);
1243 Lookup.Result r2 = serial.lookup(new Lookup.Template(String.class));
1245 assertEquals ("One item", 1, r2.allItems ().size ());
1246 Object one = r2.allItems().iterator().next ();
1247 assertEquals ("The right class", SerialPair.class, one.getClass());
1248 SerialPair p = (SerialPair)one;
1250 assertEquals ("p.instanceOf has not been queried", 0, p.countInstanceOf);
1253 /** Checks the iterator */
1254 private <T> void checkIterator(String msg, Iterator<? extends T> it1, List<? extends T> list) {
1256 Iterator<? extends T> it2 = list.iterator();
1257 while (it1.hasNext () && it2.hasNext ()) {
1262 fail (msg + " iterator[" + cnt + "] = " + n1 + " but list[" + cnt + "] = " + n2);
1268 if (it1.hasNext ()) {
1269 fail ("Iterator has more elements than list");
1272 if (it2.hasNext ()) {
1273 fail ("List has more elements than iterator");
1278 public void testResultsAreUnmodifyableOrAtLeastTheyDoNotPropagateToCache() throws Exception {
1283 Lookup.Result res = lookup.lookup(new Template(String.class));
1285 for (int i = 1; i < 5; i++) {
1286 Collection c1 = res.allInstances();
1287 Collection c2 = res.allClasses();
1288 Collection c3 = res.allItems();
1290 assertTrue(i + ": c1 has it", c1.contains(s));
1291 assertTrue(i + ": c2 has it", c2.contains(s.getClass()));
1292 assertEquals(i + ": c3 has one", 1, c3.size());
1293 Lookup.Item item = (Lookup.Item) c3.iterator().next();
1294 assertEquals(i + ": c3 has it", s, item.getInstance());
1298 assertEquals("No elements now", 0, c1.size());
1299 } catch (UnsupportedOperationException ex) {
1300 // ok, this need not be supported
1303 c2.remove(s.getClass());
1304 assertEquals("No elements now", 0, c2.size());
1305 } catch (UnsupportedOperationException ex) {
1306 // ok, this need not be supported
1310 assertEquals("No elements now", 0, c3.size());
1311 } catch (UnsupportedOperationException ex) {
1312 // ok, this need not be supported
1317 public void testSomeProblemWithDVBFrameworkSeemsToBeInLookup() {
1318 for (int i = 0; i < 5; i++) {
1320 assertEquals("Can be found", lookup, lookup.lookup(lookup.getClass()));
1321 ic.set(Collections.EMPTY_LIST, null);
1325 public void testListeningAndQueryingByTwoListenersInstances() {
1326 doListeningAndQueryingByTwoListeners(0);
1328 public void testListeningAndQueryingByTwoListenersClasses() {
1329 doListeningAndQueryingByTwoListeners(1);
1331 public void testListeningAndQueryingByTwoListenersItems() {
1332 doListeningAndQueryingByTwoListeners(2);
1336 private void doListeningAndQueryingByTwoListeners(final int type) {
1337 class L implements LookupListener {
1338 Lookup.Result integer = lookup.lookup(new Template(Integer.class));
1339 Lookup.Result number = lookup.lookup(new Template(Number.class));
1340 Lookup.Result serial = lookup.lookup(new Template(Serializable.class));
1343 integer.addLookupListener(this);
1344 number.addLookupListener(this);
1345 serial.addLookupListener(this);
1350 public void resultChanged(LookupEvent ev) {
1351 Collection c1 = get(type, integer);
1352 Collection c2 = get(type, number);
1353 Collection c3 = get(type, serial);
1355 assertEquals("round " + round + " c1 vs. c2", c1, c2);
1356 assertEquals("round " + round + " c1 vs. c3", c1, c3);
1357 assertEquals("round " + round + " c2 vs. c3", c2, c3);
1362 private Collection get(int type, Lookup.Result res) {
1365 case 0: c = res.allInstances(); break;
1366 case 1: c = res.allClasses(); break;
1367 case 2: c = res.allItems(); break;
1368 default: c = null; fail("Type: " + type); break;
1372 return new ArrayList(c);
1376 L listener = new L();
1377 listener.resultChanged(null);
1379 for(int i = 0; i < 100; i++) {
1380 ic.add(new Integer(i));
1383 assertEquals("3x100+1 checks", 301, listener.round);
1386 public void testChangeOfNodeDoesNotFireChangeInActionMap() {
1387 ActionMap am = new ActionMap();
1388 Lookup s = Lookups.singleton(am);
1389 doChangeOfNodeDoesNotFireChangeInActionMap(am, s, false);
1391 public void testChangeOfNodeDoesNotFireChangeInActionMapSimple() {
1392 ActionMap am = new ActionMap();
1393 Lookup s = Lookups.singleton(am);
1394 doChangeOfNodeDoesNotFireChangeInActionMap(am, s, true);
1397 public void testChangeOfNodeDoesNotFireChangeInActionMapWithBeforeLookupSimple() {
1398 doChangeOfNodeDoesNotFireChangeInActionMapWithBeforeLookup(true);
1401 public void testChangeOfNodeDoesNotFireChangeInActionMapWithBeforeLookup() {
1402 doChangeOfNodeDoesNotFireChangeInActionMapWithBeforeLookup(false);
1404 private void doChangeOfNodeDoesNotFireChangeInActionMapWithBeforeLookup(boolean wrapBySimple) {
1405 final ActionMap am = new ActionMap();
1407 class Before extends AbstractLookup {
1408 public InstanceContent ic;
1410 this(new InstanceContent());
1413 private Before(InstanceContent ic) {
1418 protected @Override void beforeLookup(Template template) {
1426 Before s = new Before();
1427 doChangeOfNodeDoesNotFireChangeInActionMap(am, s, wrapBySimple);
1429 assertNull("beforeLookup called once", s.ic);
1432 private void doChangeOfNodeDoesNotFireChangeInActionMap(final ActionMap am, Lookup actionMapLookup, final boolean wrapBySimple) {
1433 Lookup[] lookups = { lookup, actionMapLookup };
1435 class Provider implements Lookup.Provider {
1436 ProxyLookup delegate;
1439 public Provider(Lookup[] arr) {
1441 delegate = new ProxyLookup(arr);
1442 query = Lookups.proxy(this);
1444 query = delegate = new ProxyLookup(arr);
1448 public Lookup getLookup() {
1452 public void setLookups(Lookup... arr) {
1454 delegate = new ProxyLookup(arr);
1456 delegate.setLookups(arr);
1461 Provider p = new Provider(lookups);
1463 Lookup.Result res = p.query.lookup(new Lookup.Template(ActionMap.class));
1465 res.addLookupListener(ll);
1467 Collection c = res.allInstances();
1468 assertFalse("Has next", c.isEmpty());
1470 ActionMap am1 = (ActionMap)c.iterator().next();
1471 assertEquals("Am is there", am, am1);
1473 assertEquals("No change in first get", 0, ll.getCount());
1475 Object m1 = new InputMap();
1476 Object m2 = new InputMap();
1479 assertEquals("No change in ActionMap 1", 0, ll.getCount());
1480 ic.set(Collections.singletonList(m2), null);
1481 assertEquals("No change in ActionMap 2", 0, ll.getCount());
1483 assertEquals("No change in ActionMap 3", 0, ll.getCount());
1484 p.setLookups(lookup, actionMapLookup, Lookup.EMPTY);
1485 assertEquals("No change in ActionMap 4", 0, ll.getCount());
1487 ActionMap am2 = p.query.lookup(ActionMap.class);
1488 assertEquals("Still the same action map", am, am2);
1491 class Before extends AbstractLookup {
1492 public InstanceContent ic;
1494 this(new InstanceContent());
1497 private Before(InstanceContent ic) {
1502 protected @Override void beforeLookup(Template template) {
1510 Before s = new Before();
1512 // adding different Before, but returning the same instance
1513 // this happens with metaInfServices lookup often, moreover
1514 // it adds the instance in beforeLookup, which confuses a lot
1515 p.setLookups(new Lookup[]{ lookup, new Before() });
1516 assertEquals("No change in ActionMap 5", 0, ll.getCount());
1521 public void testTasklistsCase() throws Exception {
1522 ic.remove(new Object());
1527 public void testMultipleListeners() {
1528 Object object = new ImplementationObject();
1531 Listener[] listeners = new Listener[4];
1532 Lookup.Result result = lookup.lookup(new Lookup.Template(LookupObject.class));
1533 for(int i = 0; i < listeners.length; ++i) {
1534 listeners[i] = new Listener();
1535 result.addLookupListener(listeners[i]);
1537 // initialize listening
1542 // Apparently, only odd-numbered listeners get called when there are multiple LookupListeners on a result
1543 //for(int i = 0; i < listeners.length; ++i) {
1544 // System.out.println("Listener " + i + ": " + listeners[i].wasCalled());
1546 for(int i = 0; i < listeners.length; ++i) {
1547 assertTrue("Listener " + i + " called", listeners[i].wasCalled());
1551 static Object reserialize(Object o) throws Exception {
1552 ByteArrayOutputStream os = new ByteArrayOutputStream();
1553 ObjectOutputStream oos = new ObjectOutputStream(os);
1557 ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
1558 ObjectInputStream ois = new ObjectInputStream(is);
1559 return ois.readObject();
1562 private class Listener implements LookupListener {
1563 private boolean listenerCalled = false;
1565 public void resultChanged(LookupEvent ev) {
1566 listenerCalled = true;
1569 public boolean wasCalled() {
1570 return listenerCalled;
1573 public void reset() {
1574 listenerCalled = false;
1578 private interface LookupObject {}
1579 private class ImplementationObject implements LookupObject {}
1580 private class NullObject implements LookupObject {}
1583 public void testReturnSomethingElseThenYouClaimYouWillReturn() {
1584 class Liar extends AbstractLookup.Pair {
1587 protected boolean instanceOf(Class c) {
1588 return c.isAssignableFrom(String.class);
1591 protected boolean creatorOf(Object obj) {
1592 return this.obj == obj;
1595 public Object getInstance() {
1599 public Class getType() {
1600 return String.class;
1603 public String getId() {
1604 return String.class.getName();
1607 public String getDisplayName() {
1613 Liar l = new Liar();
1614 l.obj = new Integer(5);
1618 Collection c = lookup.lookup(new Lookup.Template(String.class)).allInstances();
1619 assertTrue("It is empty: " + c, c.isEmpty());
1622 public void testCanProxyLookupHaveWrongResults() {
1623 class L implements LookupListener {
1625 Lookup.Result<String> original;
1626 Lookup.Result<String> wrapped;
1629 public void test() {
1630 pl = new ProxyLookup(lookup);
1631 original = lookup.lookupResult(String.class);
1633 original.addLookupListener(this);
1635 wrapped = pl.lookupResult(String.class);
1637 assertEquals("Original empty", 0, original.allInstances().size());
1638 assertEquals("Wrapped empty", 0, wrapped.allInstances().size());
1643 public void resultChanged(LookupEvent ev) {
1646 assertEquals("Original has hello", 1, original.allInstances().size());
1647 assertEquals("Wrapped has hello", 1, wrapped.allInstances().size());
1651 L listener = new L();
1653 assertTrue("Listener called", listener.ok);
1656 public void testObjectFromInstanceContentConverterDisappearsIfNotReferenced() {
1657 Conv converter = new Conv("foo");
1658 ic.add (converter, converter);
1659 Lookup lkp = instanceLookup;
1660 StringBuilder sb = lookup.lookup (StringBuilder.class);
1662 int hash = System.identityHashCode(sb);
1663 assertEquals ("foo", sb.toString());
1664 Reference<StringBuilder> r = new WeakReference<StringBuilder>(sb);
1666 assertGC("Lookup held onto object", r);
1667 sb = lookup.lookup (StringBuilder.class);
1668 assertNotSame(hash, System.identityHashCode(sb));
1669 r = new WeakReference<StringBuilder>(sb);
1671 assertGC("Lookup held onto object", r);
1672 ic.remove (converter, converter);
1673 Reference <InstanceContent.Convertor> cref = new WeakReference<InstanceContent.Convertor>(converter);
1675 assertGC("Converter still referenced", cref);
1677 sb = lkp.lookup(StringBuilder.class);
1678 assertNull ("Converter removed from lookup, but object it " +
1679 "created still present:'" + sb +"'", sb);
1680 converter = new Conv("bar");
1681 ic.add (converter, converter);
1682 assertNotNull (lkp.lookup(StringBuilder.class));
1683 assertEquals ("bar", lkp.lookup(StringBuilder.class).toString());
1686 private static class Conv implements InstanceContent.Convertor<Conv, StringBuilder> {
1687 private final String str;
1688 private Conv (String str) {
1692 public StringBuilder convert(Conv obj) {
1693 return new StringBuilder (str);
1696 public Class<? extends StringBuilder> type(Conv obj) {
1697 return StringBuilder.class;
1700 public String id(Conv obj) {
1704 public String displayName(Conv obj) {
1709 public void testCanGCResults() throws Exception {
1710 class L implements LookupListener {
1713 public void resultChanged(LookupEvent ev) {
1718 L listener1 = new L();
1719 L listener2 = new L();
1721 Lookup.Result<String> res1 = this.instanceLookup.lookupResult(String.class);
1722 Lookup.Result<String> res2 = this.lookup.lookupResult(String.class);
1724 assertEquals("Empty1", 0, res1.allItems().size());
1725 assertEquals("Empty2", 0, res2.allItems().size());
1727 res1.addLookupListener(listener1);
1728 res2.addLookupListener(listener2);
1730 addInstances(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
1731 this.ic.add("Ahoj");
1733 assertEquals("Change1", 1, listener1.cnt);
1734 assertEquals("Change2", 1, listener2.cnt);
1736 assertEquals("Full1", 1, res1.allItems().size());
1737 assertEquals("Full2", 1, res2.allItems().size());
1740 Reference<Object> ref2 = new WeakReference<Object>(res2);
1742 assertGC("Result can disappear", ref2);
1745 void beforeActualTest(String n) {
1746 if (n.equals("testEqualsIsNotCalledTooMuch")) {
1748 CntPair.hashCnt = 0;
1749 CntPair.instances = 0;
1752 for(int i = 0; i < how; i++) {
1753 this.ic.addPair(new CntPair("x" + i));
1756 assertEquals("No equals called", 0, CntPair.cnt);
1757 assertEquals("1000 instances ", how, CntPair.instances);
1761 public void testEqualsIsNotCalledTooMuch() throws Exception {
1762 // most of the work done in beforeActualTest
1764 // desirable: assertEquals("no comparitions", 0, CntPair.cnt);
1765 // works for InheritanceTree, but not for ArrayStorage, but array
1766 // storages are generally small
1768 if (CntPair.cnt > 12000) {
1769 fail("Too much comparitions " + CntPair.cnt);
1771 if (CntPair.hashCnt > 40000) {
1772 fail("Too much hashes: " + CntPair.hashCnt);
1775 assertEquals("instaces is enough", 1000, CntPair.instances);
1778 /** Adds instances to the instance lookup.
1780 private void addInstances (Object... instances) {
1781 for (int i = 0; i < instances.length; i++) {
1782 ic.add(instances[i]);
1786 /** Count instances of clazz in an array. */
1787 private int countInstances (Object[] objs, Class clazz) {
1789 for (int i = 0; i < objs.length; i++) {
1790 if (clazz.isInstance(objs[i])) count++;
1795 /** Counting listener */
1796 protected static class LL implements LookupListener {
1797 private int count = 0;
1798 public Object source;
1799 public Thread changesIn;
1805 public LL (Object source) {
1806 this.source = source;
1809 public void resultChanged(LookupEvent ev) {
1810 if (changesIn != null) {
1811 assertEquals("Changes in the same thread", changesIn, Thread.currentThread());
1813 changesIn = Thread.currentThread();
1816 if (source != null) {
1817 assertSame ("Source is the same", source, ev.getSource ());
1818 // assertSame ("Result is the same", source, ev.getResult ());
1822 public int getCount() {
1829 /** A set of interfaces for testInterfaceInheritance
1831 interface TestInterfaceInheritanceA {}
1832 interface TestInterfaceInheritanceB extends TestInterfaceInheritanceA, java.rmi.Remote {}
1833 interface TestInterfaceInheritanceBB extends TestInterfaceInheritanceB {}
1834 interface TestInterfaceInheritanceC extends TestInterfaceInheritanceA, java.rmi.Remote {}
1835 interface TestInterfaceInheritanceD extends TestInterfaceInheritanceA {}
1837 /** A special class for garbage test */
1838 public static final class Garbage extends Object implements Serializable {
1839 static final long serialVersionUID = 435340912534L;
1843 /* A classloader that can load one class in a special way */
1844 private static class CL extends ClassLoader {
1849 public @Override Class findClass(String name) throws ClassNotFoundException {
1850 if (name.equals (Garbage.class.getName ())) {
1851 String n = name.replace ('.', '/');
1852 java.io.InputStream is = getClass ().getResourceAsStream ("/" + n + ".class");
1853 byte[] arr = new byte[8096];
1855 int cnt = is.read (arr);
1856 if (cnt == arr.length) {
1857 fail ("Buffer to load the class is not big enough");
1860 return defineClass (name, arr, 0, cnt);
1861 } catch (java.io.IOException ex) {
1862 ex.printStackTrace();
1863 fail ("IO Exception");
1871 /** Convert obj to other object. There is no need to implement
1872 * cache mechanism. It is provided by AbstractLookup.Item.getInstance().
1873 * Method should be called more than once because Lookup holds
1874 * just weak reference.
1876 public Object convert(Object obj) {
1880 /** Return type of converted object. */
1881 public Class type(Object obj) {
1883 return loadClass (Garbage.class.getName ());
1884 } catch (ClassNotFoundException ex) {
1885 fail ("Class not found");
1886 throw new InternalError ();
1891 private static final class CntPair extends AbstractLookup.Pair {
1892 private static int instances;
1895 public CntPair(String txt) {
1900 public static int hashCnt;
1902 public int hashCode() {
1904 return txt.hashCode() + 3777;
1907 public static int cnt;
1909 public boolean equals(Object obj) {
1915 if (getClass() != obj.getClass()) {
1918 final CntPair other = (CntPair) obj;
1919 if (this.txt != other.txt && (this.txt == null || !this.txt.equals(other.txt))) {
1925 protected boolean instanceOf(Class c) {
1926 return c.isAssignableFrom(String.class);
1929 protected boolean creatorOf(Object obj) {
1933 public Object getInstance() {
1937 public Class getType() {
1938 return String.class;
1941 public String getId() {
1945 public String getDisplayName() {
1951 public static final class SerialPair extends AbstractLookup.Pair
1952 implements java.io.Serializable {
1953 static final long serialVersionUID = 54305834L;
1954 private Object value;
1955 public transient int countInstanceOf;
1957 public SerialPair (Object value) {
1961 protected boolean creatorOf(Object obj) {
1962 return obj == value;
1965 public String getDisplayName() {
1969 public String getId() {
1970 return value.toString();
1973 public Object getInstance() {
1977 public Class getType() {
1978 return value.getClass ();
1981 protected boolean instanceOf(Class c) {
1983 return c.isInstance(value);
1985 } // end of SerialPair
1987 private static class BrokenPair extends AbstractLookup.Pair {
1988 private transient ThreadLocal IN = new ThreadLocal ();
1989 private boolean checkModify;
1990 private boolean checkQuery;
1992 public BrokenPair (boolean checkModify, boolean checkQuery) {
1993 this.checkModify = checkModify;
1994 this.checkQuery = checkQuery;
1997 protected boolean creatorOf(Object obj) { return this == obj; }
1998 public String getDisplayName() { return "Broken"; }
1999 public String getId() { return "broken"; }
2000 public Object getInstance() { return this; }
2001 public Class getType() { return getClass (); }
2002 protected boolean instanceOf(Class c) {
2005 if (IN.get () == null) {
2008 // broken behaviour, tries to modify the lookup
2009 // queries have to survive
2011 running.lookup.lookup (java.awt.List.class);
2014 // creation of new result has to survive as well
2015 Lookup.Result myQuery = running.lookup.lookup (new Lookup.Template (java.awt.Button.class));
2016 Collection all = myQuery.allItems ();
2026 // modifications should fail
2030 running.ic.addPair (new SerialPair (""));
2031 fail ("Modification from a query should be prohibited");
2032 } catch (IllegalStateException ex) {
2036 running.ic.removePair (this);
2037 fail ("This has to throw the exception");
2038 } catch (IllegalStateException ex) {
2041 running.ic.setPairs (Collections.EMPTY_SET);
2042 fail ("This has to throw the exception as well");
2043 } catch (IllegalStateException ex) {
2047 return c.isAssignableFrom(getType ());
2049 } // end of BrokenPair
2051 private static class Broken2Pair extends AbstractLookup.Pair {
2052 static final long serialVersionUID = 4532587018501L;
2053 public transient ThreadLocal IN;
2055 public Broken2Pair () {
2058 private void writeObject (java.io.ObjectOutputStream oos) throws java.io.IOException {
2061 private void readObject (java.io.ObjectInputStream ois) throws java.io.IOException, ClassNotFoundException {
2062 IN = new ThreadLocal ();
2065 protected boolean creatorOf(Object obj) { return this == obj; }
2066 public String getDisplayName() { return "Broken"; }
2067 public String getId() { return "broken"; }
2068 public Object getInstance() { return this; }
2069 public Class getType() { return getClass (); }
2070 protected boolean instanceOf(Class c) {
2072 // behaviour gets broken only after deserialization
2073 if (IN != null && IN.get () == null) {
2077 // creation of new result has to survive as well
2078 Lookup.Result myQuery = running.lookup.lookup (new Lookup.Template (java.awt.List.class));
2079 Collection all = myQuery.allItems ();
2085 return c.isAssignableFrom(getType ());
2087 } // end of Broken2Pair