|
What this is
Other links
The source code/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is NetBeans. The Initial Developer of the Original * Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun * Microsystems, Inc. All Rights Reserved. */ package org.openide.util.lookup; import org.openide.filesystems.*; import org.openide.loaders.*; import org.openide.util.*; import java.lang.ref.WeakReference; import java.util.*; import junit.framework.*; import org.netbeans.junit.*; import java.io.Serializable; public class AbstractLookupBaseHid extends NbTestCase { private static AbstractLookupBaseHid running; /** instance content to work with */ InstanceContent ic; /** the lookup to work on */ protected Lookup instanceLookup; /** the lookup created to work with */ private Lookup lookup; /** implementation of methods that can influence the behaviour */ Impl impl; protected AbstractLookupBaseHid(java.lang.String testName, Impl impl) { super(testName); if (impl == null && (this instanceof Impl)) { impl = (Impl)this; } this.impl = impl; } protected void setUp () { this.ic = new InstanceContent (); this.instanceLookup = createInstancesLookup (ic); this.lookup = createLookup (instanceLookup); running = this; } protected void tearDown () { running = null; } /** The methods to influence test behaviour */ public static interface Impl { /** Creates the initial abstract lookup. */ public Lookup createInstancesLookup (InstanceContent ic); /** Creates an lookup for given lookup. This class just returns * the object passed in, but subclasses can be different. * @param lookup in lookup * @return a lookup to use */ public Lookup createLookup (Lookup lookup); /** If the impl has any caches that would prevent the system * to not garbage collect correctly, then clear them now. */ public void clearCaches (); } private Lookup createInstancesLookup (InstanceContent ic) { return impl.createInstancesLookup (ic); } private Lookup createLookup (Lookup lookup) { return impl.createLookup (lookup); } /** instances that we register */ private static Object[] INSTANCES = new Object[] { new Integer (10), new Object () }; /** Test if first is really first. */ public void testFirst () { Object i1 = new Integer (1); Object i2 = new Integer (2); ic.add (i1); ic.add (i2); Object found = lookup.lookup (Integer.class); if (found != i1) { fail ("First object is not first: " + found + " != " + i1); } ArrayList list = new ArrayList (); list.add (i2); list.add (i1); ic.set (list, null); found = lookup.lookup (Integer.class); if (found != i2) { fail ("Second object is not first after reorder: " + found + " != " + i2); } } /** Tests ordering of items in the lookup. */ public void testOrder () { addInstances (INSTANCES); if (INSTANCES[0] != lookup.lookup (INSTANCES[0].getClass ())) { fail ("First object in intances not found"); } Iterator all = lookup.lookup (new Lookup.Template (Object.class)).allInstances ().iterator (); checkIterator ("Difference between instances added and found", all, Arrays.asList (INSTANCES)); } /** Checks the reorder of items in lookup reflects the result. * Testing both classes and interfaces, because they are often treated * especially. */ public void testReorder () { String s1 = "s2"; String s2 = "s1"; Runnable r1 = new Runnable () { public void run () {} }; Runnable r2 = new Runnable () { public void run () {} }; ArrayList l = new ArrayList (); l.add (s1); l.add (s2); l.add (r1); l.add (r2); ic.set (l, null); assertEquals ("s1 is found", s1, lookup.lookup (String.class)); assertEquals ("r1 is found", r1, lookup.lookup (Runnable.class)); Collections.reverse (l); ic.set (l, null); assertEquals ("s2 is found", s2, lookup.lookup (String.class)); assertEquals ("r2 is found", r2, lookup.lookup (Runnable.class)); } /** Tries to set empty collection to the lookup. */ public void testSetEmpty () { ic.add ("A serializable string"); lookup.lookup (Serializable.class); ic.set (Collections.EMPTY_LIST, null); } /** Tests a more complex reorder on nodes. */ public void testComplexReorder () { Integer i1 = new Integer (1); Long i2 = new Long (2); ArrayList l = new ArrayList (); l.add (i1); l.add (i2); ic.set (l, null); assertEquals ("Find integer", i1, lookup.lookup (Integer.class)); assertEquals ("Find long", i2, lookup.lookup (Long.class)); assertEquals ("Find number", i1, lookup.lookup (Number.class)); Collections.reverse (l); ic.set (l, null); assertEquals ("Find integer", i1, lookup.lookup (Integer.class)); assertEquals ("Find long", i2, lookup.lookup (Long.class)); assertEquals ("Find number", i2, lookup.lookup (Number.class)); } /** Checks whether setPairs keeps the order. */ public void testSetPairs () { // test setPairs method ArrayList li = new ArrayList(); li.addAll (Arrays.asList (INSTANCES)); ic.set (li, null); Lookup.Result res = lookup.lookup (new Lookup.Template (Object.class)); Iterator all = res.allInstances ().iterator (); checkIterator ("Original order not kept", all, li); // reverse the order Collections.reverse (li); // change the pairs LL listener = new LL (res); res.addLookupListener (listener); ic.set (li, null); if (listener.getCount () != 1) { fail ("Result has not changed even we set reversed order"); } all = res.allInstances ().iterator (); checkIterator ("Reversed order not kept", all, li); } /** Checks whether setPairs fires correct events. */ public void testSetPairsFire () { // test setPairs method ArrayList li = new ArrayList(); li.addAll (Arrays.asList (INSTANCES)); ic.set (li, null); Lookup.Result res = lookup.lookup (new Lookup.Template (Integer.class)); Iterator all = res.allInstances ().iterator (); checkIterator ("Integer is not there", all, Collections.nCopies (1, INSTANCES[0])); // change the pairs LL listener = new LL (res); res.addLookupListener (listener); ArrayList l2 = new ArrayList (li); l2.remove (INSTANCES[0]); ic.set (l2, null); all = lookup.lookup (new Lookup.Template (Object.class)).allInstances ().iterator (); checkIterator ("The removed integer is not noticed", all, l2); if (listener.getCount () != 1) { fail ("Nothing has not been fired"); } } /** Checks whether set pairs does not fire when they should not. */ public void testSetPairsDoesNotFire () { Object tmp = new Object (); ArrayList li = new ArrayList(); li.add (tmp); li.addAll (Arrays.asList (INSTANCES)); ic.set (li, null); Lookup.Result res = lookup.lookup (new Lookup.Template (Integer.class)); Iterator all = res.allInstances ().iterator (); checkIterator ("Integer is not there", all, Collections.nCopies (1, INSTANCES[0])); // change the pairs LL listener = new LL (res); res.addLookupListener (listener); ArrayList l2 = new ArrayList (li); l2.remove (tmp); ic.set (l2, null); all = lookup.lookup (new Lookup.Template (Object.class)).allInstances ().iterator (); checkIterator ("The removed integer is not noticed", all, l2); if (listener.getCount () != 0) { fail ("Something has been fired"); } } /** Test whether after registration it is possible to find registered objects * */ public void testLookupAndAdd () throws Exception { addInstances (INSTANCES); for (int i = 0; i < INSTANCES.length; i++) { Object obj = INSTANCES[i]; findAll (lookup, obj.getClass (), true); } } /** Tries to find all classes and superclasses in the lookup. */ private void findAll (Lookup lookup, Class clazz, boolean shouldBeThere) { if (clazz == null) return; Object found = lookup.lookup (clazz); if (found == null) { if (shouldBeThere) { // should find at either instance or something else, but must // find at least something fail ("Lookup (" + clazz.getName () + ") found nothing"); } } else { if (!shouldBeThere) { // should find at either instance or something else, but must // find at least something fail ("Lookup (" + clazz.getName () + ") found " + found); } } Lookup.Result res = lookup.lookup (new Lookup.Template (clazz)); Collection collection = res.allInstances (); for (int i = 0; i < INSTANCES.length; i++) { boolean isSubclass = clazz.isInstance (INSTANCES[i]); boolean isThere = collection.contains (INSTANCES[i]); if (isSubclass != isThere) { // a problem found // should find at either instance or something else, but must // find at least something fail ("Lookup.Result (" + clazz.getName () + ") for " + INSTANCES[i] + " is subclass: " + isSubclass + " isThere: " + isThere); } } // go on for superclasses findAll (lookup, clazz.getSuperclass (), shouldBeThere); Class[] ies = clazz.getInterfaces (); for (int i = 0; i < ies.length; i++) { findAll (lookup, ies[i], shouldBeThere); } } /** Test if it is possible to remove a registered object. */ public void testRemoveRegisteredObject() { Integer inst = new Integer(10); ic.add(inst); if (lookup.lookup(inst.getClass()) == null) { // should find an instance fail("Lookup (" + inst.getClass().getName () + ") found nothing"); } ic.remove(inst); if (lookup.lookup(inst.getClass()) != null) { // should NOT find an instance fail("Lookup (" + inst.getClass().getName () + ") found an instance after remove operation"); } } public void testCanReturnReallyStrangeResults () throws Exception { class QueryingPair extends org.openide.util.lookup.AbstractLookup.Pair { private Integer i = new Integer (434); // // do the test // public void doTest () throws Exception { ic.add (i); ic.addPair (this); Object found = lookup.lookup (QueryingPair.class); assertEquals ("This object is found", this, found); } // // Implementation of pair // public java.lang.String getId() { return getType ().toString(); } public java.lang.String getDisplayName() { return getId (); } public java.lang.Class getType() { return getClass (); } protected boolean creatorOf(java.lang.Object obj) { return obj == this; } protected boolean instanceOf(java.lang.Class c) { assertEquals ("Integer found or exception is thrown", i, lookup.lookup (Integer.class)); return c.isAssignableFrom(getType ()); } public java.lang.Object getInstance() { return this; } } QueryingPair qp = new QueryingPair (); qp.doTest (); } /** Test of firing events. */ public void testLookupListener() { Integer inst = new Integer(10); Lookup.Result res = lookup.lookup(new Lookup.Template(inst.getClass())); res.allInstances (); LL listener = new LL(res); res.addLookupListener(listener); ic.add(inst); if (listener.getCount() == 0) { fail("None event fired during NbLookup.addPair()"); } ic.remove(inst); if (listener.getCount() == 0) { fail("None event fired during NbLookup.removePair()"); } ic.add(inst); if (listener.getCount() == 0) { fail("None event fired during second NbLookup.addPair()"); } ic.remove(inst); if (listener.getCount() == 0) { fail("None event fired during second NbLookup.removePair()"); } } /** Testing identity of the lookup. */ public void testId () { AbstractLookup.Template templ; int cnt; addInstances (INSTANCES); AbstractLookup.Result res = lookup.lookup (new AbstractLookup.Template ()); Iterator it; it = res.allItems ().iterator (); while (it.hasNext ()) { AbstractLookup.Item item = (AbstractLookup.Item)it.next (); templ = new AbstractLookup.Template (null, item.getId (), null); cnt = lookup.lookup (templ).allInstances ().size (); if (cnt != 1) { fail ("Identity lookup failed. Instances = " + cnt); } templ = new AbstractLookup.Template (item.getType (), item.getId (), null); cnt = lookup.lookup (templ).allInstances ().size (); if (cnt != 1) { fail ("Identity lookup with type failed. Instances = " + cnt); } templ = new AbstractLookup.Template (this.getClass (), item.getId (), null); cnt = lookup.lookup (templ).allInstances ().size (); if (cnt != 0) { fail ("Identity lookup with wrong type failed. Instances = " + cnt); } templ = new AbstractLookup.Template (null, null, item.getInstance ()); cnt = lookup.lookup (templ).allInstances ().size (); if (cnt != 1) { fail ("Instance lookup failed. Instances = " + cnt); } templ = new AbstractLookup.Template (null, item.getId (), item.getInstance ()); cnt = lookup.lookup (templ).allInstances ().size (); if (cnt != 1) { fail ("Instance & identity lookup failed. Instances = " + cnt); } } } /** Tests adding and removing. */ public void testAddAndRemove () throws Exception { Object map = new javax.swing.ActionMap (); LL ll = new LL (); Lookup.Result res = lookup.lookup (new Lookup.Template (map.getClass ())); res.allItems(); res.addLookupListener (ll); ll.source = res; ic.add (map); assertEquals ("First change when adding", ll.getCount (), 1); ic.remove (map); assertEquals ("Second when removing", ll.getCount (), 1); ic.add (map); assertEquals ("Third when readding", ll.getCount (), 1); ic.remove (map); assertEquals ("Forth when reremoving", ll.getCount (), 1); } /** Will a class garbage collect even it is registered in lookup. */ public void testGarbageCollect () throws Exception { ClassLoader l = new CL (); Class c = l.loadClass (Garbage.class.getName ()); WeakReference ref = new WeakReference (c); lookup.lookup (c); // now test garbage collection c = null; l = null; impl.clearCaches (); assertGC ("The classloader has not been garbage collected!", ref); } /** Items are the same as results. */ public void testItemsAndIntances () { addInstances (INSTANCES); Lookup.Template t = new Lookup.Template (Object.class); Lookup.Result r = lookup.lookup (t); Collection items = r.allItems (); Collection insts = r.allInstances (); if (items.size () != insts.size ()) { fail ("Different size of sets"); } Iterator it = items.iterator (); while (it.hasNext ()) { Lookup.Item item = (Lookup.Item)it.next (); if (!insts.contains (item.getInstance ())) { fail ("Intance " + item.getInstance () + " is missing in " + insts); } } } /** Checks search for interface. */ public void testSearchForInterface () { Lookup.Template t = new Lookup.Template (Serializable.class, null, null); assertNull("Nothing to find", lookup.lookupItem (t)); Serializable s = new Serializable () {}; ic.add (s); Lookup.Item item = lookup.lookupItem (t); assertNotNull ("Something found", item); } /** Test to add broken item if it incorrectly answers instanceOf questions. */ public void testIncorectInstanceOf40364 () { final Long sharedLong = new Long (0); class P extends AbstractLookup.Pair { public boolean isLong; P (boolean b) { isLong = b; } protected boolean creatorOf (Object obj) { return obj == sharedLong; } public String getDisplayName () { return ""; } public String getId () { return ""; } public Object getInstance () { return sharedLong; } public Class getType () { return isLong ? Long.class : Number.class; } protected boolean instanceOf (Class c) { return c.isAssignableFrom (getType ()); } public int hashCode () { return getClass ().hashCode (); } public boolean equals (Object obj) { return obj != null && getClass ().equals (obj.getClass ()); } } // to create the right structure in the lookup lookup.lookup (Object.class); lookup.lookup (Long.class); lookup.lookup (Number.class); P lng1 = new P (true); ic.addPair (lng1); P lng2 = new P (false); ic.setPairs (Collections.singleton (lng2)); Collection res = lookup.lookup (new Lookup.Template (Object.class)).allItems (); assertEquals ("Just one pair", 1, res.size ()); } /** Testing lookup of inherited classes. */ public void testInheritance() { class A {} class B extends A implements java.rmi.Remote {} class BB extends B {} class C extends A implements java.rmi.Remote {} class D extends A {} A[] types = {new B(), new BB(), new C(), new D()}; for (int i = 0; i < types.length; i++) { ic.add(types[i]); if (lookup.lookup(types[i].getClass()) == null) { // should find an instance fail("Lookup (" + types[i].getClass().getName () + ") found nothing"); } } int size1, size2; //interface query size1 = lookup.lookup(new Lookup.Template(java.rmi.Remote.class)).allInstances().size(); size2 = countInstances(types, java.rmi.Remote.class); if (size1 != size2) fail("Lookup with interface failed: " + size1 + " != " + size2); // superclass query size1 = lookup.lookup(new Lookup.Template(A.class)).allInstances().size(); size2 = countInstances(types, A.class); if (size1 != size2) fail("Lookup with superclass failed: " + size1 + " != " + size2); } /** Test interface inheritance. */ public void testInterfaceInheritance() { testInterfaceInheritanceA[] types = { new testInterfaceInheritanceB() {}, new testInterfaceInheritanceBB() {}, new testInterfaceInheritanceC() {}, new testInterfaceInheritanceD() {} }; for (int i = 0; i < types.length; i++) { ic.add(types[i]); if (lookup.lookup(types[i].getClass()) == null) { // should find an instance fail("Lookup (" + types[i].getClass().getName () + ") found nothing"); } } int size1, size2; //interface query LL l = new LL (); Lookup.Result res = lookup.lookup(new Lookup.Template(java.rmi.Remote.class)); l.source = res; size1 = res.allInstances().size(); size2 = countInstances(types, java.rmi.Remote.class); if (size1 != size2) fail("Lookup with interface failed: " + size1 + " != " + size2); // superclass query size1 = lookup.lookup(new Lookup.Template(testInterfaceInheritanceA.class)).allInstances().size(); size2 = countInstances(types, testInterfaceInheritanceA.class); if (size1 != size2) fail("Lookup with superclass failed: " + size1 + " != " + size2); res.addLookupListener (l); ic.remove (types[0]); if (l.getCount () != 1) { fail ("No notification that a Remote is removed"); } } /** Checks whether the AbstractLookup is guarded against modifications * while doing some kind of modification. */ public void testModificationArePreventedWhenDoingModifications () throws Exception { BrokenPair broken = new BrokenPair (true, false); ic.addPair (broken); Lookup.Template templ = new Lookup.Template (BrokenPair.class); Object item = lookup.lookupItem (templ); assertEquals ("Broken is found", broken, item); } public void testModificationArePreventedWhenDoingModificationsResult () throws Exception { BrokenPair broken = new BrokenPair (false, true); ic.addPair (broken); Lookup.Template templ = new Lookup.Template (BrokenPair.class); Collection c = lookup.lookup (templ).allInstances(); assertEquals ("One item", 1, c.size ()); assertEquals ("Broken is found again", broken, c.iterator().next ()); } public void testModificationArePreventedWhenDoingModificationsItemAndResult () throws Exception { BrokenPair broken = new BrokenPair (false, true); ic.addPair (broken); Lookup.Template templ = new Lookup.Template (BrokenPair.class); Object item = lookup.lookupItem (templ); assertEquals ("Broken is found", broken, item); Collection c = lookup.lookup (templ).allInstances(); assertEquals ("One item", 1, c.size ()); assertEquals ("Broken is found again", broken, c.iterator().next ()); } public void testModificationArePreventedWhenDoingModificationsResultAndItem () throws Exception { BrokenPair broken = new BrokenPair (false, true); ic.addPair (broken); Lookup.Template templ = new Lookup.Template (BrokenPair.class); Collection c = lookup.lookup (templ).allInstances(); assertEquals ("One item", 1, c.size ()); assertEquals ("Broken is found again", broken, c.iterator().next ()); Object item = lookup.lookupItem (templ); assertEquals ("Broken is found", broken, item); } public void testAddALotOfPairsIntoTheLookupOneByOne () throws Exception { Lookup.Result res = lookup.lookup (new Lookup.Template (Integer.class)); for (int i = 0; i < 1000; i++) { ic.add (new Integer (i)); } assertEquals ( "there is the right count", 1000, res.allItems().size () ); } public void testAddALotOfPairsIntoTheLookup () throws Exception { ArrayList arr = new ArrayList (); for (int i = 0; i < 1000; i++) { arr.add (new Integer (i)); } ic.set (arr, null); assertEquals ( "there is the right count", 1000, lookup.lookup (new Lookup.Template (Integer.class)).allItems().size () ); } public void testDoubleAddIssue35274 () throws Exception { class P extends AbstractLookup.Pair { protected boolean creatorOf(Object obj) { return false; } public String getDisplayName() { return ""; } public String getId() { return ""; } public Object getInstance() { return null; } public Class getType() { return Object.class; } protected boolean instanceOf(Class c) { return c.isAssignableFrom(getType ()); } public int hashCode () { return getClass ().hashCode(); }; public boolean equals (Object obj) { return getClass () == obj.getClass (); }; } P p = new P (); ic.addPair (p); ic.addPair (p); Lookup.Result result = lookup.lookup (new Lookup.Template (Object.class)); Collection res = result.allItems (); assertEquals ("One item there", 1, res.size ()); assertTrue ("It is the p", p == res.iterator ().next ()); P p2 = new P (); ic.addPair (p2); WeakReference ref = new WeakReference (result); result = null; assertGC ("The result can disappear", ref); impl.clearCaches (); result = lookup.lookup (new Lookup.Template (Object.class)); res = result.allItems (); assertEquals ("One item is still there", 1, res.size ()); assertTrue ("But the p2 replaced p", p2 == res.iterator ().next ()); } /** Test for proper serialization. */ public void testSerializationSupport () throws Exception { doSerializationSupport (1); } public void testDoubleSerializationSupport () throws Exception { doSerializationSupport (2); } private void doSerializationSupport (int count) throws Exception { if (lookup instanceof Serializable) { ic.addPair (new SerialPair ("1")); ic.addPair (new SerialPair ("2")); ic.addPair (new SerialPair ("3")); Lookup l = (Lookup)new org.openide.util.io.NbMarshalledObject (lookup).get (); assertEquals ("Able to answer simple query", "1", l.lookup (String.class)); assertEquals ("Three objects there", 3, l.lookup (new Lookup.Template (String.class)).allInstances().size ()); while (count-- > 0) { l = (Lookup)new org.openide.util.io.NbMarshalledObject (l).get (); } assertEquals ("Able to answer simple query", "1", l.lookup (String.class)); assertEquals ("Three objects there", 3, l.lookup (new Lookup.Template (String.class)).allInstances().size ()); } } /** When a lookup with two different versions of the same class * get's serialized, the results may be very bad. */ public void testSerializationOfTwoClassesWithTheSameName () throws Exception { if (lookup instanceof Serializable) { doTwoSerializedClasses (false, false); } } public void testSerializationOfTwoClassesWithTheSameNameButQueryBeforeSave () throws Exception { if (lookup instanceof Serializable) { doTwoSerializedClasses (true, false); } } public void testSerializationOfTwoClassesWithTheSameNameWithBroken () throws Exception { if (lookup instanceof Serializable) { doTwoSerializedClasses (false, true); } } public void testSerializationOfTwoClassesWithTheSameNameButQueryBeforeSaveWithBroken () throws Exception { if (lookup instanceof Serializable) { doTwoSerializedClasses (true, true); } } private void doTwoSerializedClasses (boolean queryBeforeSerialization, boolean useBroken) throws Exception { ClassLoader loader = new CL (); Class c = loader.loadClass (Garbage.class.getName ()); // in case of InheritanceTree it creates a slot for class Garbage lookup.lookup(c); // but creates new instance and adds it into the lookup // without querying for it loader = new CL (); c = loader.loadClass (Garbage.class.getName ()); Object theInstance = c.newInstance (); ic.addPair (new SerialPair (theInstance)); Broken2Pair broken = null; if (useBroken) { broken = new Broken2Pair (); ic.addPair (broken); assertNull ( "We need to create the slot for the List as " + "the Broken2Pair will ask for it after deserialization", lookup.lookup (java.awt.List.class) ); } if (queryBeforeSerialization) { assertEquals ("Instance is found", theInstance, lookup.lookup (c)); } // replace the old lookup with new one lookup = (Lookup)new org.openide.util.io.NbMarshalledObject (lookup).get (); Lookup.Result result = lookup.lookup (new Lookup.Template (Garbage.class)); assertEquals ("One item is the result", 1, result.allInstances ().size ()); Object r = result.allInstances ().iterator ().next (); assertNotNull("A value is found", r); assertEquals ("It is of the right class", Garbage.class, r.getClass()); } /** Test of reorder and item change which used to fail on interfaces. */ public void testReoderingIssue13779 () throws Exception { LinkedList arr = new LinkedList (); class R extends Exception implements Cloneable { } Object o1 = new R (); Object o2 = new R (); Object o3 = new R (); arr.add (o1); arr.add (o2); ic.set (arr, null); Lookup.Result objectResult = lookup.lookup (new Lookup.Template (Exception.class)); Lookup.Result interfaceResult = lookup.lookup (new Lookup.Template (Cloneable.class)); objectResult.allItems (); interfaceResult.allItems (); LL l1 = new LL (objectResult); LL l2 = new LL (interfaceResult); objectResult.addLookupListener(l1); interfaceResult.addLookupListener(l2); arr.addFirst (o3); ic.set (arr, null); assertEquals ("One change on objects", 1, l1.getCount ()); assertEquals ("One change on interfaces", 1, l2.getCount ()); arr.addFirst (new Cloneable () { }); ic.set (arr, null); assertEquals ("No change on objects", 0, l1.getCount ()); assertEquals ("But one change on interfaces", 1, l2.getCount ()); } public void testDeadlockBetweenProxyResultAndLookupIssue47772 () throws Exception { final String myModule = "My Module"; ic.add (myModule); class MyProxy extends ProxyLookup { public MyProxy () { super (new Lookup[] { lookup }); } } final MyProxy my = new MyProxy (); final Lookup.Result allModules = my.lookup (new Lookup.Template (String.class)); class PairThatNeedsInfoAboutModules extends AbstractLookup.Pair { public String getDisplayName () { return "Need a module"; } public String getId () { return getDisplayName (); } public Class getType () { return Integer.class; } protected boolean instanceOf (Class c) { if (c == Integer.class) { synchronized (this) { notifyAll (); try { wait (1000); } catch (InterruptedException ex) { fail (ex.getMessage ()); } } java.util.Collection coll = allModules.allInstances (); assertEquals ("Size is 1", 1, coll.size ()); assertEquals ("My module is there", myModule, coll.iterator ().next ()); } return c.isAssignableFrom (Integer.class); } public Object getInstance () { return new Integer (10); } protected boolean creatorOf (Object obj) { return new Integer (10).equals (obj); } } PairThatNeedsInfoAboutModules pair = new PairThatNeedsInfoAboutModules (); ic.addPair (pair); synchronized (pair) { class BlockInInstanceOf implements Runnable { public void run () { Integer i = (Integer)my.lookup (Integer.class); assertEquals (new Integer (10), i); } } BlockInInstanceOf blk = new BlockInInstanceOf (); RequestProcessor.getDefault ().post (blk); pair.wait (); } java.util.Collection coll = allModules.allInstances (); assertEquals ("Size is 1", 1, coll.size ()); assertEquals ("My module is there", myModule, coll.iterator ().next ()); } public void testAWayToGenerateProblem13779 () { ic.add (new Integer (1)); ic.add (new Integer (2)); ic.add (new Integer (1)); ic.add (new Integer (2)); Collection c = lookup.lookup (new Lookup.Template (Integer.class)).allInstances (); assertEquals ("There are two objects", 2, c.size ()); } /** Replacing items with different objects. */ public void testReplacingObjectsDoesNotGenerateException () throws Exception { LinkedList arr = new LinkedList (); class R extends Exception implements Cloneable { } arr.add (new R ()); arr.add (new R ()); ic.set (arr, null); arr.clear(); arr.add (new R ()); arr.add (new R ()); ic.set (arr, null); } public void testAfterDeserializationNoQueryIsPeformedOnAlreadyQueriedObjects() throws Exception { if (! (lookup instanceof Serializable)) { // well this test works only for serializable lookups return; } SerialPair my = new SerialPair ("no"); ic.addPair (my); Lookup.Result res = lookup.lookup (new Lookup.Template (String.class)); assertEquals ("One instance", 1, res.allInstances().size ()); assertEquals ("my.instanceOf called once", 1, my.countInstanceOf); Lookup serial = (Lookup)new org.openide.util.io.NbMarshalledObject (lookup).get (); Lookup.Result r2 = serial.lookup(new Lookup.Template(String.class)); assertEquals ("One item", 1, r2.allItems ().size ()); Object one = r2.allItems().iterator().next (); assertEquals ("The right class", SerialPair.class, one.getClass()); SerialPair p = (SerialPair)one; assertEquals ("p.instanceOf has not been queried", 0, p.countInstanceOf); } /** Checks the iterator */ private void checkIterator (String msg, Iterator it1, List list) { int cnt = 0; Iterator it2 = list.iterator (); while (it1.hasNext () && it2.hasNext ()) { Object n1 = it1.next (); Object n2 = it2.next (); if (n1 != n2) { fail (msg + " iterator[" + cnt + "] = " + n1 + " but list[" + cnt + "] = " + n2); } cnt++; } if (it1.hasNext ()) { fail ("Iterator has more elements than list"); } if (it2.hasNext ()) { fail ("List has more elements than iterator"); } } /** Adds instances to the instance lookup. */ private void addInstances (Object[] instances) { for (int i = 0; i < instances.length; i++) { ic.add(instances[i]); } } /** Count instances of clazz in an array. */ private int countInstances (Object[] objs, Class clazz) { int count = 0; for (int i = 0; i < objs.length; i++) { if (clazz.isInstance(objs[i])) count++; } return count; } /** Counting listener */ protected static class LL implements LookupListener { private int count = 0; public Object source; public LL () { this (null); } public LL (Object source) { this.source = source; } public void resultChanged(LookupEvent ev) { ++count; if (source != null) { assertSame ("Source is the same", source, ev.getSource ()); // assertSame ("Result is the same", source, ev.getResult ()); } } public int getCount() { int i = count; count = 0; return i; } }; /** A set of interfaces for testInterfaceInheritance */ interface testInterfaceInheritanceA {} interface testInterfaceInheritanceB extends testInterfaceInheritanceA, java.rmi.Remote {} interface testInterfaceInheritanceBB extends testInterfaceInheritanceB {} interface testInterfaceInheritanceC extends testInterfaceInheritanceA, java.rmi.Remote {} interface testInterfaceInheritanceD extends testInterfaceInheritanceA {} /** A special class for garbage test */ public static final class Garbage extends Object implements Serializable { static final long serialVersionUID = 435340912534L; } /* A classloader that can load one class in a special way */ private static class CL extends ClassLoader { public CL () { super (null); } public Class findClass (String name) throws ClassNotFoundException { if (name.equals (Garbage.class.getName ())) { String n = name.replace ('.', '/'); java.io.InputStream is = getClass ().getResourceAsStream ("/" + n + ".class"); byte[] arr = new byte[8096]; try { int cnt = is.read (arr); if (cnt == arr.length) { fail ("Buffer to load the class is not big enough"); } return defineClass (name, arr, 0, cnt); } catch (java.io.IOException ex) { ex.printStackTrace(); fail ("IO Exception"); return null; } } else { return null; } } /** Convert obj to other object. There is no need to implement * cache mechanism. It is provided by AbstractLookup.Item.getInstance(). * Method should be called more than once because Lookup holds * just weak reference. */ public Object convert(Object obj) { return null; } /** Return type of converted object. */ public Class type(Object obj) { try { return loadClass (Garbage.class.getName ()); } catch (ClassNotFoundException ex) { fail ("Class not found"); throw new InternalError (); } } } public static final class SerialPair extends AbstractLookup.Pair implements java.io.Serializable { static final long serialVersionUID = 54305834L; private Object value; public transient int countInstanceOf; public SerialPair (Object value) { this.value = value; } protected boolean creatorOf(Object obj) { return obj == value; } public String getDisplayName() { return getId (); } public String getId() { return value.toString(); } public Object getInstance() { return value; } public Class getType() { return value.getClass (); } protected boolean instanceOf(Class c) { countInstanceOf++; return c.isInstance(value); } } // end of SerialPair private static class BrokenPair extends AbstractLookup.Pair { private transient ThreadLocal IN = new ThreadLocal (); private boolean checkModify; private boolean checkQuery; public BrokenPair (boolean checkModify, boolean checkQuery) { this.checkModify = checkModify; this.checkQuery = checkQuery; } protected boolean creatorOf(Object obj) { return this == obj; } public String getDisplayName() { return "Broken"; } public String getId() { return "broken"; } public Object getInstance() { return this; } public Class getType() { return getClass (); } protected boolean instanceOf(Class c) { if (checkQuery) { if (IN.get () == null) { try { IN.set (this); // broken behaviour, tries to modify the lookup // queries have to survive running.lookup.lookup (java.awt.List.class); // // creation of new result has to survive as well Lookup.Result myQuery = running.lookup.lookup (new Lookup.Template (java.awt.Button.class)); Collection all = myQuery.allItems (); } finally { IN.set (null); } } } if (checkModify) { // // modifications should fail // try { running.ic.addPair (new SerialPair ("")); fail ("Modification from a query should be prohibited"); } catch (IllegalStateException ex) { } try { running.ic.removePair (this); fail ("This has to throw the exception"); } catch (IllegalStateException ex) { } try { running.ic.setPairs (Collections.EMPTY_SET); fail ("This has to throw the exception as well"); } catch (IllegalStateException ex) { } } return c.isAssignableFrom(getType ()); } } // end of BrokenPair private static class Broken2Pair extends AbstractLookup.Pair { static final long serialVersionUID = 4532587018501L; public transient ThreadLocal IN; public Broken2Pair () { } private void writeObject (java.io.ObjectOutputStream oos) throws java.io.IOException { } private void readObject (java.io.ObjectInputStream ois) throws java.io.IOException, ClassNotFoundException { IN = new ThreadLocal (); } protected boolean creatorOf(Object obj) { return this == obj; } public String getDisplayName() { return "Broken"; } public String getId() { return "broken"; } public Object getInstance() { return this; } public Class getType() { return getClass (); } protected boolean instanceOf(Class c) { // behaviour gets broken only after deserialization if (IN != null && IN.get () == null) { try { IN.set (this); // creation of new result has to survive as well Lookup.Result myQuery = running.lookup.lookup (new Lookup.Template (java.awt.List.class)); Collection all = myQuery.allItems (); } finally { IN.set (null); } } return c.isAssignableFrom(getType ()); } } // end of Broken2Pair } |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.