Issue #169844: do not fire changes from MetaInfServicesLookup just because someone asked for results. diff --git a/openide.util/src/org/openide/util/lookup/MetaInfServicesLookup.java b/openide.util/src/org/openide/util/lookup/MetaInfServicesLookup.java --- a/openide.util/src/org/openide/util/lookup/MetaInfServicesLookup.java +++ b/openide.util/src/org/openide/util/lookup/MetaInfServicesLookup.java @@ -60,6 +60,7 @@ import java.util.logging.Level; import java.util.logging.Logger; import org.openide.util.Lookup; +import org.openide.util.RequestProcessor; /** * @author Jaroslav Tulach, Jesse Glick @@ -69,6 +70,7 @@ final class MetaInfServicesLookup extends AbstractLookup { private static final Logger LOGGER = Logger.getLogger(MetaInfServicesLookup.class.getName()); + static final RequestProcessor RP = new RequestProcessor(MetaInfServicesLookup.class.getName(), 1); private static int knownInstancesCount; private static final List> knownInstances; static { @@ -118,9 +120,6 @@ // Added new class, search for it. LinkedHashSet> arr = getPairsAsLHS(); search(c, arr); - - // listeners are notified under while holding lock on class c, - // let say it is acceptable now listeners = setPairsAndCollectListeners(arr); } else { // ok, nothing needs to be done @@ -130,7 +129,7 @@ NotifyListeners notify = new NotifyListeners(listeners); if (notify.shallRun()) { - notify.run(); + RP.post(notify); } } diff --git a/openide.util/test/unit/src/org/openide/util/lookup/MetaInfServicesLookupTest.java b/openide.util/test/unit/src/org/openide/util/lookup/MetaInfServicesLookupTest.java --- a/openide.util/test/unit/src/org/openide/util/lookup/MetaInfServicesLookupTest.java +++ b/openide.util/test/unit/src/org/openide/util/lookup/MetaInfServicesLookupTest.java @@ -62,8 +62,7 @@ import java.util.Set; import java.util.TreeSet; import java.util.WeakHashMap; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.jar.JarEntry; import java.util.jar.JarOutputStream; import java.util.logging.Level; @@ -389,39 +388,26 @@ assertGC("Class can be garbage collected", ref); } - public void testListenersAreNotifiedWithoutHoldingALockIssue36035() throws Exception { - final Lookup l = getTestedLookup(c2); - final Class xface = c1.loadClass("org.foo.Interface"); - final Lookup.Result res = l.lookup(new Lookup.Template(Object.class)); - - class L implements LookupListener, Runnable { - private Thread toInterrupt; - - public void run() { - assertNotNull("Possible to query lookup", l.lookup(xface)); - assertEquals("and there are two items", 2, res.allInstances().size()); - toInterrupt.interrupt(); - } - - public synchronized void resultChanged(LookupEvent ev) { - toInterrupt = Thread.currentThread(); - Executors.newSingleThreadScheduledExecutor().schedule(this, 0, TimeUnit.MICROSECONDS); - try { - wait(3000); - fail("Should be interrupted - means it was not possible to finish query in run() method"); - } catch (InterruptedException ex) { - // this is what we want + public void testSuperTypes() throws Exception { + doTestSuperTypes(createLookup(c2)); + doTestSuperTypes(new ProxyLookup(createLookup(c2))); + } + private void doTestSuperTypes(Lookup l) throws Exception { + final Class xface = c1.loadClass("org.foo.Interface"); + final Lookup.Result res = l.lookupResult(Object.class); + assertEquals("Nothing yet", 0, res.allInstances().size()); + final AtomicBoolean event = new AtomicBoolean(); + final Thread here = Thread.currentThread(); + res.addLookupListener(new LookupListener() { + public void resultChanged(LookupEvent ev) { + if (Thread.currentThread() == here) { + event.set(true); } } - } - L listener = new L(); - - res.addLookupListener(listener); - assertEquals("Nothing yet", 0, res.allInstances().size()); - + }); assertNotNull("Interface found", l.lookup(xface)); - assertNotNull("Listener notified", listener.toInterrupt); - + assertFalse(event.get()); + MetaInfServicesLookup.RP.post(new Runnable() {public void run() {}}).waitFinished(); assertEquals("Now two", 2, res.allInstances().size()); }