This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

View | Details | Raw Unified | Return to bug 169844
Collapse All | Expand All

(-)a/openide.util/src/org/openide/util/lookup/MetaInfServicesLookup.java (-25 / +9 lines)
Lines 55-65 Link Here
55
import java.util.HashSet;
55
import java.util.HashSet;
56
import java.util.LinkedHashSet;
56
import java.util.LinkedHashSet;
57
import java.util.List;
57
import java.util.List;
58
import java.util.Map;
58
import java.util.Set;
59
import java.util.WeakHashMap;
60
import java.util.logging.Level;
59
import java.util.logging.Level;
61
import java.util.logging.Logger;
60
import java.util.logging.Logger;
62
import org.openide.util.Lookup;
61
import org.openide.util.Lookup;
62
import org.openide.util.WeakSet;
63
63
64
/**
64
/**
65
 * @author Jaroslav Tulach, Jesse Glick
65
 * @author Jaroslav Tulach, Jesse Glick
Lines 84-90 Link Here
84
     * However we also hold classes which are definitely not loadable by
84
     * However we also hold classes which are definitely not loadable by
85
     * our loader.
85
     * our loader.
86
     */
86
     */
87
    private final Map<Class,Object> classes = new WeakHashMap<Class,Object>();
87
    private final Set<Class> classes = new WeakSet<Class>();
88
88
89
    /** class loader to use */
89
    /** class loader to use */
90
    private final ClassLoader loader;
90
    private final ClassLoader loader;
Lines 108-136 Link Here
108
    /* Tries to load appropriate resources from manifest files.
108
    /* Tries to load appropriate resources from manifest files.
109
     */
109
     */
110
    @Override
110
    @Override
111
    protected final void beforeLookup(Lookup.Template t) {
111
    protected synchronized final void beforeLookup(Lookup.Template t) {
112
        Class c = t.getType();
112
        Class c = t.getType();
113
113
        if (classes.add(c)) {
114
        HashSet<AbstractLookup.R> listeners;
114
            // Added new class, search for it.
115
115
            LinkedHashSet<AbstractLookup.Pair<?>> arr = getPairsAsLHS();
116
        synchronized (this) {
116
            search(c, arr);
117
            if (classes.put(c, "") == null) { // NOI18N
117
            setPairsAndCollectListeners(arr); // #169844: do not notify
118
                // Added new class, search for it.
119
                LinkedHashSet<AbstractLookup.Pair<?>> arr = getPairsAsLHS();
120
                search(c, arr);
121
122
                // listeners are notified under while holding lock on class c, 
123
                // let say it is acceptable now
124
                listeners = setPairsAndCollectListeners(arr);
125
            } else {
126
                // ok, nothing needs to be done
127
                return;
128
            }
129
        }
130
131
        NotifyListeners notify = new NotifyListeners(listeners);
132
        if (notify.shallRun()) {
133
            notify.run();
134
        }
118
        }
135
    }
119
    }
136
120
(-)a/openide.util/test/unit/src/org/openide/util/lookup/MetaInfServicesLookupTest.java (-34 / +3 lines)
Lines 62-69 Link Here
62
import java.util.Set;
62
import java.util.Set;
63
import java.util.TreeSet;
63
import java.util.TreeSet;
64
import java.util.WeakHashMap;
64
import java.util.WeakHashMap;
65
import java.util.concurrent.Executors;
66
import java.util.concurrent.TimeUnit;
67
import java.util.jar.JarEntry;
65
import java.util.jar.JarEntry;
68
import java.util.jar.JarOutputStream;
66
import java.util.jar.JarOutputStream;
69
import java.util.logging.Level;
67
import java.util.logging.Level;
Lines 74-81 Link Here
74
import org.netbeans.junit.MockServices;
72
import org.netbeans.junit.MockServices;
75
import org.netbeans.junit.NbTestCase;
73
import org.netbeans.junit.NbTestCase;
76
import org.openide.util.Lookup;
74
import org.openide.util.Lookup;
77
import org.openide.util.LookupEvent;
78
import org.openide.util.LookupListener;
79
import org.openide.util.test.MockLookup;
75
import org.openide.util.test.MockLookup;
80
76
81
/** Test finding services from manifest.
77
/** Test finding services from manifest.
Lines 389-427 Link Here
389
        assertGC("Class can be garbage collected", ref);
385
        assertGC("Class can be garbage collected", ref);
390
    }
386
    }
391
387
392
    public void testListenersAreNotifiedWithoutHoldingALockIssue36035() throws Exception {
388
    public void testSuperTypes() throws Exception {
393
        final Lookup l = getTestedLookup(c2);
389
        final Lookup l = getTestedLookup(c2);
394
        final Class xface = c1.loadClass("org.foo.Interface");
390
        final Class<?> xface = c1.loadClass("org.foo.Interface");
395
        final Lookup.Result res = l.lookup(new Lookup.Template(Object.class));
391
        final Lookup.Result<Object> res = l.lookupResult(Object.class);
396
397
        class L implements LookupListener, Runnable {
398
            private Thread toInterrupt;
399
400
            public void run() {
401
                assertNotNull("Possible to query lookup", l.lookup(xface));
402
                assertEquals("and there are two items", 2, res.allInstances().size());
403
                toInterrupt.interrupt();
404
            }
405
406
            public synchronized void resultChanged(LookupEvent ev) {
407
                toInterrupt = Thread.currentThread();
408
                Executors.newSingleThreadScheduledExecutor().schedule(this, 0, TimeUnit.MICROSECONDS);
409
                try {
410
                    wait(3000);
411
                    fail("Should be interrupted - means it was not possible to finish query in run() method");
412
                } catch (InterruptedException ex) {
413
                    // this is what we want
414
                }
415
            }
416
        }
417
        L listener = new L();
418
419
        res.addLookupListener(listener);
420
        assertEquals("Nothing yet", 0, res.allInstances().size());
392
        assertEquals("Nothing yet", 0, res.allInstances().size());
421
422
        assertNotNull("Interface found", l.lookup(xface));
393
        assertNotNull("Interface found", l.lookup(xface));
423
        assertNotNull("Listener notified", listener.toInterrupt);
424
425
        assertEquals("Now two", 2, res.allInstances().size());
394
        assertEquals("Now two", 2, res.allInstances().size());
426
    }
395
    }
427
    
396
    

Return to bug 169844