KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > java > source > classpath > GlobalSourcePathTest


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.java.source.classpath;
21
22 import java.beans.PropertyChangeSupport JavaDoc;
23 import java.io.File JavaDoc;
24 import java.io.IOException JavaDoc;
25 import java.util.Iterator JavaDoc;
26 import java.util.LinkedList JavaDoc;
27 import java.util.concurrent.CountDownLatch JavaDoc;
28 import java.util.concurrent.ExecutorService JavaDoc;
29 import java.util.concurrent.Executors JavaDoc;
30 import junit.framework.*;
31 import java.beans.PropertyChangeListener JavaDoc;
32 import java.net.URL JavaDoc;
33 import java.util.ArrayList JavaDoc;
34 import java.util.HashMap JavaDoc;
35 import java.util.HashSet JavaDoc;
36 import java.util.List JavaDoc;
37 import java.util.Map JavaDoc;
38 import java.util.Set JavaDoc;
39 import javax.swing.event.ChangeEvent JavaDoc;
40 import javax.swing.event.ChangeListener JavaDoc;
41 import org.netbeans.api.java.classpath.ClassPath;
42 import org.netbeans.api.java.classpath.GlobalPathRegistry;
43 import org.netbeans.api.java.queries.SourceForBinaryQuery;
44 import org.netbeans.junit.NbTestCase;
45 import org.netbeans.modules.java.source.usages.IndexUtil;
46 import org.netbeans.spi.java.classpath.ClassPathFactory;
47 import org.netbeans.spi.java.classpath.ClassPathImplementation;
48 import org.netbeans.spi.java.classpath.PathResourceImplementation;
49 import org.netbeans.spi.java.classpath.support.ClassPathSupport;
50 import org.netbeans.spi.java.queries.SourceForBinaryQueryImplementation;
51 import org.openide.filesystems.FileObject;
52 import org.openide.filesystems.FileUtil;
53 import org.openide.util.Lookup;
54 import org.openide.util.lookup.Lookups;
55 import org.openide.util.lookup.ProxyLookup;
56
57 /**
58  *
59  * @author Tomas Zezula
60  */

61 public class GlobalSourcePathTest extends NbTestCase {
62     
63     private FileObject srcRoot1;
64     private FileObject srcRoot2;
65     private FileObject srcRoot3;
66     private FileObject compRoot1;
67     private FileObject compRoot2;
68     private FileObject bootRoot1;
69     private FileObject bootRoot2;
70     private FileObject compSrc1;
71     private FileObject compSrc2;
72     private FileObject bootSrc1;
73     private FileObject unknown1;
74     private FileObject unknown2;
75     private FileObject unknownSrc2;
76     
77     static {
78         GlobalSourcePathTest.class.getClassLoader().setDefaultAssertionStatus(true);
79         System.setProperty("org.openide.util.Lookup", GlobalSourcePathTest.Lkp.class.getName());
80         Assert.assertEquals(GlobalSourcePathTest.Lkp.class, Lookup.getDefault().getClass());
81     }
82     
83     public static class Lkp extends ProxyLookup {
84         
85         private static Lkp DEFAULT;
86         
87         public Lkp () {
88             Assert.assertNull(DEFAULT);
89             DEFAULT = this;
90             ClassLoader JavaDoc l = Lkp.class.getClassLoader();
91             this.setLookups(
92                  new Lookup [] {
93                     Lookups.metaInfServices(l),
94                     Lookups.fixed (new Object JavaDoc[] {DeadLockSFBQImpl.getDefault (), SFBQImpl.getDefault (),l}),
95             });
96         }
97         
98     }
99     
100     
101     public GlobalSourcePathTest(String JavaDoc testName) {
102         super(testName);
103     }
104
105     protected @Override JavaDoc void setUp() throws Exception JavaDoc {
106         this.clearWorkDir();
107         File JavaDoc _wd = this.getWorkDir();
108         FileObject wd = FileUtil.toFileObject(_wd);
109         File JavaDoc cacheFolder = new File JavaDoc (_wd,"cache");
110         cacheFolder.mkdirs();
111         IndexUtil.setCacheFolder(cacheFolder);
112         assertNotNull("No masterfs",wd);
113         srcRoot1 = wd.createFolder("src1");
114         assertNotNull(srcRoot1);
115         srcRoot2 = wd.createFolder("src2");
116         assertNotNull(srcRoot2);
117         srcRoot3 = wd.createFolder("src3");
118         assertNotNull (srcRoot3);
119         compRoot1 = wd.createFolder("comp1");
120         assertNotNull (compRoot1);
121         compRoot2 = wd.createFolder("comp2");
122         assertNotNull (compRoot2);
123         bootRoot1 = wd.createFolder("boot1");
124         assertNotNull (bootRoot1);
125         bootRoot2 = wd.createFolder("boot2");
126         assertNotNull (bootRoot2);
127         compSrc1 = wd.createFolder("cs1");
128         assertNotNull (compSrc1);
129         compSrc2 = wd.createFolder("cs2");
130         assertNotNull (compSrc2);
131         bootSrc1 = wd.createFolder("bs1");
132         assertNotNull (bootSrc1);
133         unknown1 = wd.createFolder("uknw1");
134         assertNotNull (unknown1);
135         unknown2 = wd.createFolder("uknw2");
136         assertNotNull (unknown2);
137         unknownSrc2 = wd.createFolder("uknwSrc2");
138         assertNotNull(unknownSrc2);
139         SFBQImpl q = SFBQImpl.getDefault();
140         q.register (bootRoot1,bootSrc1);
141         q.register (compRoot1,compSrc1);
142         q.register (compRoot2,compSrc2);
143         q.register (unknown2,unknownSrc2);
144     }
145
146     protected @Override JavaDoc void tearDown() throws Exception JavaDoc {
147     }
148
149     public void testGlobalSourcePath () throws Exception JavaDoc {
150         GlobalPathRegistry regs = GlobalPathRegistry.getDefault();
151         GlobalSourcePath gcp = GlobalSourcePath.getDefault();
152         ClassPathImplementation cpi = ClassPathSupport.createProxyClassPathImplementation(new ClassPathImplementation[] {gcp.getSourcePath(), gcp.getUnknownSourcePath()});
153         List JavaDoc<? extends PathResourceImplementation> impls = cpi.getResources();
154         assertNotNull (impls);
155         assertEquals(0,impls.size());
156         //Testing classpath registration
157
MutableClassPathImplementation mcpi1 = new MutableClassPathImplementation ();
158         mcpi1.addResource(this.srcRoot1);
159         ClassPath cp1 = ClassPathFactory.createClassPath(mcpi1);
160         regs.register(ClassPath.SOURCE,new ClassPath[]{cp1});
161         impls = cpi.getResources();
162         assertNotNull (impls);
163         assertEquals(1,impls.size());
164         assertEquals(srcRoot1.getURL(),impls.get(0).getRoots()[0]);
165         //Testing changes in registered classpath
166
mcpi1.addResource(srcRoot2);
167         impls = cpi.getResources();
168         assertNotNull (impls);
169         assertEquals(2,impls.size());
170         assertEquals(new FileObject[] {srcRoot1, srcRoot2},impls);
171         mcpi1.removeResource(srcRoot1);
172         impls = cpi.getResources();
173         assertNotNull (impls);
174         assertEquals(1,impls.size());
175         assertEquals(srcRoot2.getURL(),impls.get(0).getRoots()[0]);
176         //Testing adding new ClassPath
177
MutableClassPathImplementation mcpi2 = new MutableClassPathImplementation ();
178         mcpi2.addResource(srcRoot1);
179         ClassPath cp2 = ClassPathFactory.createClassPath(mcpi2);
180         regs.register (ClassPath.SOURCE, new ClassPath[] {cp2});
181         impls = cpi.getResources();
182         assertNotNull (impls);
183         assertEquals(new FileObject[] {srcRoot2, srcRoot1},impls);
184         mcpi2.addResource(srcRoot3);
185         impls = cpi.getResources();
186         assertNotNull (impls);
187         assertEquals(new FileObject[] {srcRoot2, srcRoot1, srcRoot3},impls);
188         //Testing removing ClassPath
189
regs.unregister(ClassPath.SOURCE,new ClassPath[] {cp2});
190         impls = cpi.getResources();
191         assertNotNull (impls);
192         assertEquals(new FileObject[] {srcRoot2},impls);
193         //Testing registering classpath with SFBQ
194
ClassPath cp3 = ClassPathSupport.createClassPath(new FileObject[] {bootRoot1,bootRoot2});
195         regs.register(ClassPath.BOOT,new ClassPath[] {cp3});
196         impls = cpi.getResources();
197         assertNotNull (impls);
198         assertEquals(new FileObject[] {srcRoot2, bootSrc1},impls);
199         MutableClassPathImplementation mcpi4 = new MutableClassPathImplementation ();
200         mcpi4.addResource (compRoot1);
201         ClassPath cp4 = ClassPathFactory.createClassPath(mcpi4);
202         regs.register(ClassPath.COMPILE,new ClassPath[] {cp4});
203         impls = cpi.getResources();
204         assertNotNull (impls);
205         assertEquals(new FileObject[] {srcRoot2, bootSrc1, compSrc1},impls);
206         mcpi4.addResource(compRoot2);
207         impls = cpi.getResources();
208         assertNotNull (impls);
209         assertEquals(new FileObject[] {srcRoot2, bootSrc1, compSrc1, compSrc2},impls);
210         mcpi4.removeResource(compRoot1);
211         impls = cpi.getResources();
212         assertNotNull (impls);
213         assertEquals(new FileObject[] {srcRoot2, bootSrc1, compSrc2},impls);
214         regs.unregister(ClassPath.BOOT,new ClassPath[] {cp3});
215         impls = cpi.getResources();
216         assertNotNull (impls);
217         assertEquals(new FileObject[] {srcRoot2, compSrc2},impls);
218         //Testing listening on SFBQ.Results
219
SFBQImpl.getDefault().register(compRoot2,compSrc1);
220         impls = cpi.getResources();
221         assertNotNull (impls);
222         assertEquals(new FileObject[] {srcRoot2, compSrc1},impls);
223         SFBQImpl.getDefault().register(compRoot2,compSrc2);
224         impls = cpi.getResources();
225         assertNotNull (impls);
226         assertEquals(new FileObject[] {srcRoot2, compSrc2},impls);
227         //Test unknown source roots
228
ClassPath ucp = ClassPathSupport.createClassPath(new FileObject[] {unknown1, unknown2});
229         gcp.getSourceRootForBinaryRoot(unknown1.getURL(),ucp,true);
230         gcp.getSourceRootForBinaryRoot(unknown2.getURL(),ucp,true);
231         impls = cpi.getResources();
232         assertNotNull (impls);
233         assertEquals(new FileObject[] {srcRoot2, compSrc2, unknownSrc2},impls);
234         //Test unknown source root after gc
235
ucp = null;
236         gc(); gc();
237         impls = cpi.getResources();
238         assertNotNull (impls);
239         assertEquals(new FileObject[] {srcRoot2, compSrc2},impls);
240         //Test reregistration of unknown cp
241
ucp = ClassPathSupport.createClassPath(new FileObject[] {unknown1, unknown2});
242         gcp.getSourceRootForBinaryRoot(unknown1.getURL(),ucp,true);
243         gcp.getSourceRootForBinaryRoot(unknown2.getURL(),ucp,true);
244         impls = cpi.getResources();
245         assertNotNull (impls);
246         assertEquals(new FileObject[] {srcRoot2, compSrc2, unknownSrc2},impls);
247         ClassPath rcp = ClassPathSupport.createClassPath(new FileObject[] {unknown1, unknown2});
248         regs.register(ClassPath.COMPILE,new ClassPath[] {rcp});
249         impls = cpi.getResources();
250         assertNotNull (impls);
251         assertEquals(new FileObject[] {srcRoot2, compSrc2, unknownSrc2},impls);
252         ucp = null;
253         gc(); gc();
254         impls = cpi.getResources();
255         assertNotNull (impls);
256         assertEquals(new FileObject[] {srcRoot2, compSrc2, unknownSrc2},impls);
257         regs.unregister(ClassPath.COMPILE,new ClassPath[] {rcp});
258         impls = cpi.getResources();
259         assertNotNull (impls);
260         assertEquals(new FileObject[] {srcRoot2, compSrc2},impls);
261     }
262     
263     /**
264      * Simulates a project mutex deadlock
265      */

266     public void testProjectMutexDeadlock () throws Exception JavaDoc {
267         ExecutorService JavaDoc es = Executors.newSingleThreadExecutor();
268         final CountDownLatch JavaDoc wk_ready = new CountDownLatch JavaDoc (1);
269         final CountDownLatch JavaDoc mt_ready = new CountDownLatch JavaDoc (1);
270         try {
271             es.submit(new Runnable JavaDoc () {
272                 public void run () {
273                     try {
274                         Object JavaDoc lock = DeadLockSFBQImpl.getDefault().getLock();
275                         ClassPath cp = ClassPathSupport.createClassPath(new FileObject[] {unknown1});
276                         synchronized (lock) {
277                             wk_ready.countDown();
278                             mt_ready.await();
279                             Thread.sleep(1000);
280                             GlobalPathRegistry.getDefault().register(ClassPath.COMPILE, new ClassPath[] {cp});
281                         }
282                     } catch (InterruptedException JavaDoc e) {
283                     }
284                 }
285             });
286             ClassPath cp = ClassPathSupport.createClassPath(new FileObject[] {unknown1});
287             wk_ready.await();
288             mt_ready.countDown();
289             GlobalPathRegistry.getDefault().register(ClassPath.COMPILE, new ClassPath[] {cp});
290         } finally {
291             es.shutdownNow();
292         }
293     }
294     
295     
296     public void testRaceCondition () throws Exception JavaDoc {
297         final GlobalPathRegistry regs = GlobalPathRegistry.getDefault();
298         final GlobalSourcePath gcp = GlobalSourcePath.getDefault();
299         final int initialSize = gcp.getSourcePath().getResources().size();
300         final CountDownLatch JavaDoc state_1 = new CountDownLatch JavaDoc (1);
301         final CountDownLatch JavaDoc state_2 = new CountDownLatch JavaDoc (1);
302         final CountDownLatch JavaDoc state_3 = new CountDownLatch JavaDoc (1);
303         final CountDownLatch JavaDoc state_4 = new CountDownLatch JavaDoc (1);
304         final ExecutorService JavaDoc es = Executors.newSingleThreadExecutor();
305         gcp.setDebugCallBack(new Runnable JavaDoc (){
306             public void run () {
307                 try {
308                     state_2.countDown();
309                     state_3.await();
310                 } catch (InterruptedException JavaDoc ie) {}
311             }
312         });
313         try {
314             es.submit(new Runnable JavaDoc() {
315                 public void run () {
316                     try {
317                         state_1.await();
318                         gcp.getSourcePath().getResources();
319                         gcp.getSourcePath().getResources();
320                         state_4.countDown();
321                     } catch (InterruptedException JavaDoc ie) {}
322                 }
323             });
324             regs.register(ClassPath.SOURCE, new ClassPath[] {ClassPathSupport.createClassPath(new URL JavaDoc[] {new URL JavaDoc("file:///foo1/")})});
325             state_1.countDown();
326             state_2.await();
327             regs.register(ClassPath.SOURCE, new ClassPath[] {ClassPathSupport.createClassPath(new URL JavaDoc[] {new URL JavaDoc("file:///foo2/")})});
328             state_3.countDown();
329             state_4.await();
330             assertEquals("Race condition",initialSize+2,gcp.getSourcePath().getResources().size());
331         } finally {
332             es.shutdownNow();
333         }
334     }
335     
336     public void testRaceCondition2 () throws Exception JavaDoc {
337         final GlobalPathRegistry regs = GlobalPathRegistry.getDefault();
338         final GlobalSourcePath gcp = GlobalSourcePath.getDefault();
339         final ClassPathImplementation cp = gcp.getSourcePath();
340         final int initialSize = cp.getResources().size();
341         final CountDownLatch JavaDoc state_1 = new CountDownLatch JavaDoc (1);
342         final CountDownLatch JavaDoc state_2 = new CountDownLatch JavaDoc (1);
343         final CountDownLatch JavaDoc state_3 = new CountDownLatch JavaDoc (1);
344         final CountDownLatch JavaDoc state_4 = new CountDownLatch JavaDoc (1);
345         final ExecutorService JavaDoc es = Executors.newSingleThreadExecutor();
346         gcp.setDebugCallBack(new Runnable JavaDoc (){
347             public void run () {
348                 try {
349                     state_2.countDown();
350                     state_3.await();
351                 } catch (InterruptedException JavaDoc ie) {}
352             }
353         });
354         try {
355             es.submit(new Runnable JavaDoc() {
356                 public void run () {
357                     try {
358                         state_1.await();
359                         cp.getResources();
360                         cp.getResources();
361                         state_4.countDown();
362                     } catch (InterruptedException JavaDoc ie) {}
363                 }
364             });
365             regs.register(ClassPath.SOURCE, new ClassPath[] {ClassPathSupport.createClassPath(new URL JavaDoc[] {new URL JavaDoc("file:///foo3/")})});
366             state_1.countDown();
367             state_2.await();
368             regs.register(ClassPath.SOURCE, new ClassPath[] {ClassPathSupport.createClassPath(new URL JavaDoc[] {new URL JavaDoc("file:///foo4/")})});
369             state_3.countDown();
370             state_4.await();
371             assertEquals("Race condition",initialSize+2, cp.getResources().size());
372         } finally {
373             es.shutdownNow();
374         }
375     }
376     
377     public void testBinaryPath () throws Exception JavaDoc {
378         Set JavaDoc<ClassPath> cps = GlobalPathRegistry.getDefault().getPaths(ClassPath.SOURCE);
379         GlobalPathRegistry.getDefault().unregister(ClassPath.SOURCE, cps.toArray(new ClassPath[cps.size()]));
380         cps = GlobalPathRegistry.getDefault().getPaths(ClassPath.BOOT);
381         GlobalPathRegistry.getDefault().unregister(ClassPath.BOOT, cps.toArray(new ClassPath[cps.size()]));
382         cps = GlobalPathRegistry.getDefault().getPaths(ClassPath.COMPILE);
383         GlobalPathRegistry.getDefault().unregister(ClassPath.COMPILE, cps.toArray(new ClassPath[cps.size()]));
384         ClassPathImplementation sourcePath = GlobalSourcePath.getDefault().getSourcePath();
385         ClassPathImplementation binaryPath = GlobalSourcePath.getDefault().getBinaryPath();
386         assertEquals (0,sourcePath.getResources().size());
387         assertEquals (0,binaryPath.getResources().size());
388         
389         
390         ClassPath src = ClassPathSupport.createClassPath(new FileObject[] {srcRoot1, srcRoot2, srcRoot3});
391         ClassPath compile = ClassPathSupport.createClassPath(new FileObject[] {compRoot1, compRoot2});
392         ClassPath boot = ClassPathSupport.createClassPath(new FileObject[] {bootRoot1, bootRoot2});
393         
394         GlobalPathRegistry.getDefault().register(ClassPath.SOURCE, new ClassPath[] {src});
395         GlobalPathRegistry.getDefault().register(ClassPath.COMPILE, new ClassPath[] {compile});
396         GlobalPathRegistry.getDefault().register(ClassPath.BOOT, new ClassPath[] {boot});
397         
398         List JavaDoc<? extends PathResourceImplementation> res = sourcePath.getResources();
399         assertEquals(new FileObject[] {srcRoot1, srcRoot2, srcRoot3, compSrc1, compSrc2, bootSrc1}, res);
400         res = binaryPath.getResources();
401         assertEquals(new FileObject[] {bootRoot2}, res);
402         
403         ClassPath compile2 = ClassPathSupport.createClassPath(new FileObject[] {unknown1, unknown2});
404         GlobalPathRegistry.getDefault().register(ClassPath.COMPILE, new ClassPath[] {compile2});
405         
406         res = sourcePath.getResources();
407         assertEquals(new FileObject[] {srcRoot1, srcRoot2, srcRoot3, compSrc1, compSrc2, bootSrc1, unknownSrc2}, res);
408         res = binaryPath.getResources();
409         assertEquals(new FileObject[] {bootRoot2, unknown1}, res);
410     }
411     
412     private static void gc () {
413         System.gc();
414         long[][] spaces = new long[100][];
415         for (int i=0; i<spaces.length; i++) {
416             spaces[i] = new long[1000];
417         }
418         System.gc();
419         spaces = null;
420         System.gc();
421     }
422     
423     private void assertEquals (FileObject[] expected, List JavaDoc<? extends PathResourceImplementation> result) throws IOException JavaDoc {
424         assertEquals(expected.length, result.size());
425         Set JavaDoc<URL JavaDoc> expectedUrls = new HashSet JavaDoc ();
426         for (FileObject fo : expected) {
427             expectedUrls.add(fo.getURL());
428         }
429         for (PathResourceImplementation impl : result) {
430             URL JavaDoc url = impl.getRoots()[0];
431             if (!expectedUrls.remove (url)) {
432                 assertTrue (String.format("Unknown URL: %s in: %s", url, expectedUrls),false);
433             }
434         }
435         assertEquals(expectedUrls.toString(),0,expectedUrls.size());
436     }
437     
438     
439     private static class MutableClassPathImplementation implements ClassPathImplementation {
440         
441         private final List JavaDoc<PathResourceImplementation> res;
442         private final PropertyChangeSupport JavaDoc support;
443         
444         public MutableClassPathImplementation () {
445             res = new ArrayList JavaDoc ();
446             support = new PropertyChangeSupport JavaDoc (this);
447         }
448         
449         public void addResource (FileObject fo) throws IOException JavaDoc {
450             res.add(ClassPathSupport.createResource(fo.getURL()));
451             this.support.firePropertyChange(PROP_RESOURCES,null,null);
452         }
453         
454         public void removeResource (FileObject fo) throws IOException JavaDoc {
455             URL JavaDoc url = fo.getURL();
456             for (Iterator JavaDoc<PathResourceImplementation> it = res.iterator(); it.hasNext(); ) {
457                 PathResourceImplementation r = it.next();
458                 if (url.equals(r.getRoots()[0])) {
459                     it.remove();
460                     this.support.firePropertyChange(PROP_RESOURCES,null,null);
461                 }
462             }
463         }
464         
465         public void removePropertyChangeListener(PropertyChangeListener JavaDoc listener) {
466             support.removePropertyChangeListener(listener);
467         }
468
469         public void addPropertyChangeListener(PropertyChangeListener JavaDoc listener) {
470             support.addPropertyChangeListener(listener);
471         }
472
473         public List JavaDoc getResources() {
474             return res;
475         }
476         
477     }
478     
479     private static class SFBQImpl implements SourceForBinaryQueryImplementation {
480         
481         private static SFBQImpl instance;
482         
483         final Map JavaDoc<URL JavaDoc,FileObject> map = new HashMap JavaDoc ();
484         final Map JavaDoc<URL JavaDoc,Result> results = new HashMap JavaDoc ();
485
486         private SFBQImpl () {
487             
488         }
489         
490         public void register (FileObject binRoot, FileObject sourceRoot) throws IOException JavaDoc {
491             URL JavaDoc url = binRoot.getURL();
492             this.map.put (url,sourceRoot);
493             Result r = results.get (url);
494             if (r != null) {
495                 r.update (sourceRoot);
496             }
497         }
498         
499         public void unregister (FileObject binRoot) throws IOException JavaDoc {
500             URL JavaDoc url = binRoot.getURL();
501             this.map.remove(url);
502             Result r = results.get (url);
503             if (r != null) {
504                 r.update (null);
505             }
506         }
507         
508         public void clean () {
509             this.map.clear();
510             this.results.clear();
511         }
512         
513         public SourceForBinaryQuery.Result findSourceRoots(URL JavaDoc binaryRoot) {
514             FileObject srcRoot = this.map.get(binaryRoot);
515             if (srcRoot == null) {
516                 return null;
517             }
518             Result r = results.get (binaryRoot);
519             if (r == null) {
520                 r = new Result (srcRoot);
521                 results.put(binaryRoot, r);
522             }
523             return r;
524         }
525         
526         public static synchronized SFBQImpl getDefault () {
527             if (instance == null) {
528                 instance = new SFBQImpl ();
529             }
530             return instance;
531         }
532         
533         public static class Result implements SourceForBinaryQuery.Result {
534             
535             private FileObject root;
536             private final List JavaDoc<ChangeListener JavaDoc> listeners;
537             
538             public Result (FileObject root) {
539                 this.root = root;
540                 this.listeners = new LinkedList JavaDoc ();
541             }
542             
543             public void update (FileObject root) {
544                 this.root = root;
545                 fireChange ();
546             }
547
548             public synchronized void addChangeListener(ChangeListener JavaDoc l) {
549                 this.listeners.add(l);
550             }
551
552             public synchronized void removeChangeListener(ChangeListener JavaDoc l) {
553                 this.listeners.remove(l);
554             }
555
556             public FileObject[] getRoots() {
557                 if (this.root == null) {
558                     return new FileObject[0];
559                 }
560                 else {
561                     return new FileObject[] {this.root};
562                 }
563             }
564             
565             private void fireChange () {
566                 ChangeListener JavaDoc[] _listeners;
567                 synchronized (this) {
568                     _listeners = this.listeners.toArray(new ChangeListener JavaDoc[this.listeners.size()]);
569                 }
570                 ChangeEvent JavaDoc event = new ChangeEvent JavaDoc (this);
571                 for (ChangeListener JavaDoc l : _listeners) {
572                     l.stateChanged (event);
573                 }
574             }
575         }
576         
577     }
578     
579     private static class DeadLockSFBQImpl implements SourceForBinaryQueryImplementation {
580         
581         private static DeadLockSFBQImpl instance;
582         
583         private final Object JavaDoc lock;
584         
585         private DeadLockSFBQImpl () {
586             this.lock = new String JavaDoc ("Lock");
587         }
588         
589         public Object JavaDoc getLock () {
590             return this.lock;
591         }
592         
593         public SourceForBinaryQuery.Result findSourceRoots(URL JavaDoc binaryRoot) {
594             synchronized (lock) {
595                 lock.toString();
596             }
597             return null;
598         }
599         
600         public static synchronized DeadLockSFBQImpl getDefault () {
601             if (instance == null) {
602                 instance = new DeadLockSFBQImpl ();
603             }
604             return instance;
605         }
606         
607     }
608     
609 }
610
Popular Tags