# This patch file was generated by NetBeans IDE # Following Index: paths are relative to: /space/java/netbeans-cvs-release55/java/javacore # This patch can be applied using context Tools: Patch action on respective folder. # It uses platform neutral UTF-8 encoding and \n newlines. # Above lines and this line are ignored by the patching process. Index: src/org/netbeans/modules/javacore/classpath/MergedClassPathImplementation.java *** /space/java/netbeans-cvs-release55/java/javacore/src/org/netbeans/modules/javacore/classpath/MergedClassPathImplementation.java Base (1.24.14.1) --- /space/java/netbeans-cvs-release55/java/javacore/src/org/netbeans/modules/javacore/classpath/MergedClassPathImplementation.java Locally Modified (Based On 1.24.14.1) *************** *** 7,13 **** * http://www.sun.com/ * * The Original Code is NetBeans. The Initial Developer of the Original ! * Code is Sun Microsystems, Inc. Portions Copyright 1997-2005 Sun * Microsystems, Inc. All Rights Reserved. */ --- 7,13 ---- * http://www.sun.com/ * * The Original Code is NetBeans. The Initial Developer of the Original ! * Code is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun * Microsystems, Inc. All Rights Reserved. */ *************** *** 255,268 **** } private void updateEntries (ClassPath cp) { boolean fire = false; synchronized (this) { ! List oldResources = (List) this.resourceMap.remove (cp); assert oldResources != null : "Change in unknown classpath"; // NOI18N List newResources = addClassPathResources (cp); Collection toRemove = new HashSet (oldResources); toRemove.removeAll (newResources); --- 255,269 ---- } private void updateEntries (ClassPath cp) { + boolean fire = false; + List oldResources; synchronized (this) { ! oldResources = (List) this.resourceMap.remove (cp); assert oldResources != null : "Change in unknown classpath"; // NOI18N + } List newResources = addClassPathResources (cp); + synchronized (this) { Collection toRemove = new HashSet (oldResources); toRemove.removeAll (newResources); newResources.removeAll (oldResources); //To Add *************** *** 288,294 **** this.firePropertyChange(PROP_UNRESOLVED_ROOTS); } ! private synchronized void addClassPath (ClassPath cp) { if (this.resourceMap == null) { initEntries(); } --- 292,299 ---- this.firePropertyChange(PROP_UNRESOLVED_ROOTS); } ! private void addClassPath (ClassPath cp) { ! synchronized (this) { if (this.resourceMap == null) { initEntries(); } *************** *** 295,308 **** if (this.resourceMap.containsKey(cp)) { return; } ! List c = addClassPathResources (cp); ! this.resourceMap.put (cp,c); this.unresolvedRoots.addAll(c); cp.addPropertyChangeListener((PropertyChangeListener)WeakListeners.create(PropertyChangeListener.class,this.pcListener,cp)); } private void firePropertyChange (String propName) { --- 300,315 ---- if (this.resourceMap.containsKey(cp)) { return; } ! } ! List c = addClassPathResources(cp); ! synchronized (this) { ! if (!this.resourceMap.containsKey(cp)) { ! this.resourceMap.put(cp,c); this.unresolvedRoots.addAll(c); cp.addPropertyChangeListener((PropertyChangeListener)WeakListeners.create(PropertyChangeListener.class,this.pcListener,cp)); } + } + } private void firePropertyChange (String propName) { this.support.firePropertyChange(propName,null,null); *************** *** 345,358 **** } private List addClassPathResources (final ClassPath cp) { ! List c = new ArrayList (); WeakReference wr = (WeakReference) sfbResultListeners.get(cp); ! SFBQListener listener = (SFBQListener) (wr == null ? null : wr.get()); if (listener == null) { listener = new SFBQListener(cp); sfbResultListeners.put(cp, new WeakReference(listener)); } ! for (Iterator et = cp.entries().iterator(); et.hasNext();) { ClassPath.Entry entry = (ClassPath.Entry)et.next(); URL url = entry.getURL(); assert url != null : "ClassPath.Entry.getURL() returned null"; //NOI18N --- 355,373 ---- } private List addClassPathResources (final ClassPath cp) { ! List entries = null; ! SFBQListener listener = null; ! synchronized (this) { WeakReference wr = (WeakReference) sfbResultListeners.get(cp); ! listener = (SFBQListener) (wr == null ? null : wr.get()); if (listener == null) { listener = new SFBQListener(cp); sfbResultListeners.put(cp, new WeakReference(listener)); } ! } ! entries = cp.entries(); ! List c = new ArrayList(); ! for (Iterator et = entries.iterator(); et.hasNext();) { ClassPath.Entry entry = (ClassPath.Entry)et.next(); URL url = entry.getURL(); assert url != null : "ClassPath.Entry.getURL() returned null"; //NOI18N Index: test/unit/src/org/netbeans/modules/javacore/classpath/MergedClassPathImplementationTest.java *** /space/java/netbeans-cvs-release55/java/javacore/test/unit/src/org/netbeans/modules/javacore/classpath/MergedClassPathImplementationTest.java Base (1.3.14.1) --- /space/java/netbeans-cvs-release55/java/javacore/test/unit/src/org/netbeans/modules/javacore/classpath/MergedClassPathImplementationTest.java Locally Modified (Based On 1.3.14.1) *************** *** 7,20 **** * http://www.sun.com/ * * The Original Code is NetBeans. The Initial Developer of the Original ! * Code is Sun Microsystems, Inc. Portions Copyright 1997-2005 Sun * Microsystems, Inc. All Rights Reserved. */ package org.netbeans.modules.javacore.classpath; import java.beans.PropertyChangeSupport; - import java.beans.PropertyVetoException; import java.io.File; import java.io.IOException; import java.net.URL; --- 7,22 ---- * http://www.sun.com/ * * The Original Code is NetBeans. The Initial Developer of the Original ! * Code is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun * Microsystems, Inc. All Rights Reserved. */ package org.netbeans.modules.javacore.classpath; import java.beans.PropertyChangeSupport; import java.io.File; import java.io.IOException; *************** *** 24,29 **** --- 23,29 ---- import java.util.List; import java.util.SortedSet; import java.util.TreeSet; + import junit.framework.Assert; import org.netbeans.junit.NbTestCase; import org.netbeans.spi.java.classpath.ClassPathFactory; import org.netbeans.spi.java.classpath.ClassPathImplementation; *************** *** 31,51 **** import org.netbeans.spi.java.classpath.support.ClassPathSupport; import org.netbeans.api.java.classpath.ClassPath; import org.netbeans.api.java.classpath.GlobalPathRegistry; import org.openide.filesystems.FileObject; - import org.openide.filesystems.FileSystem; import org.openide.filesystems.FileUtil; - import org.openide.filesystems.LocalFileSystem; - import org.openide.filesystems.Repository; import org.openide.filesystems.URLMapper; /** * @author tom */ public class MergedClassPathImplementationTest extends NbTestCase { private static final String ROOT = "cproot_"; private static final int ROOT_COUNT = 6; --- 31,76 ---- import org.netbeans.spi.java.classpath.support.ClassPathSupport; import org.netbeans.api.java.classpath.ClassPath; import org.netbeans.api.java.classpath.GlobalPathRegistry; + import org.netbeans.api.java.queries.SourceForBinaryQuery.Result; + import org.netbeans.spi.java.queries.SourceForBinaryQueryImplementation; import org.openide.filesystems.FileObject; import org.openide.filesystems.FileUtil; import org.openide.filesystems.URLMapper; + import org.openide.util.Lookup; + import org.openide.util.lookup.Lookups; + import org.openide.util.lookup.ProxyLookup; /** * @author tom */ public class MergedClassPathImplementationTest extends NbTestCase { + private boolean failed; + + // Copied from org.netbeans.api.project.TestUtil: + static { + // XXX replace with MockServices + System.setProperty("org.openide.util.Lookup", Lkp.class.getName()); + Assert.assertEquals(Lkp.class, Lookup.getDefault().getClass()); + } + + public static final class Lkp extends ProxyLookup { + private static Lkp DEFAULT; + public Lkp() { + Assert.assertNull(DEFAULT); + DEFAULT = this; + setLookup(new Object[0]); + } + public static void setLookup(Object[] instances) { + ClassLoader l = Lkp.class.getClassLoader(); + DEFAULT.setLookups(new Lookup[] { + Lookups.fixed(instances), + Lookups.metaInfServices(l), + Lookups.singleton(l), + }); + } + } + private static final String ROOT = "cproot_"; private static final int ROOT_COUNT = 6; private FileObject[] roots; *************** *** 100,105 **** --- 128,163 ---- assertEquivalent (resources,new FileObject[] {roots[0],roots[1],roots[2],roots[3]}); } + public void testDeadlock() throws Exception { + // instantiate singleton + final MergedClassPathImplementation mcpi = MergedClassPathImplementation.getDefault(); + Lkp.setLookup(new Object[] { + new SourceForBinaryQueryImplementation() { + public Result findSourceRoots(URL binaryRoot) { + Thread mcpiLocker = new Thread(new Runnable() { + public void run() { + synchronized(mcpi) {} + } + }); + mcpiLocker.start(); + try { + mcpiLocker.join(); + } catch (InterruptedException ie) { + ie.printStackTrace(); + failed = true; + } + return null; + } + } + }); + final DynamicClassPath dympl = new DynamicClassPath(); + ClassPath cp = ClassPathFactory.createClassPath(dympl); + GlobalPathRegistry regs = GlobalPathRegistry.getDefault(); + regs.register(ClassPath.COMPILE, new ClassPath[] {cp}); + dympl.setRoots(new FileObject[]{roots[0]}); + assertFalse(failed); + } + private FileObject getWorkDirFileObject () throws IOException { FileObject fos = FileUtil.toFileObject(this.getWorkDir()); if (fos != null) {