KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > api > java > classpath > GlobalPathRegistryTest


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.api.java.classpath;
21
22 import java.net.URL JavaDoc;
23 import java.util.ArrayList JavaDoc;
24 import java.util.Arrays JavaDoc;
25 import java.util.Collections JavaDoc;
26 import java.util.HashMap JavaDoc;
27 import java.util.HashSet JavaDoc;
28 import java.util.Iterator JavaDoc;
29 import java.util.Set JavaDoc;
30 import java.util.Map JavaDoc;
31 import javax.swing.event.ChangeEvent JavaDoc;
32 import javax.swing.event.ChangeListener JavaDoc;
33 import org.netbeans.api.java.queries.SourceForBinaryQuery;
34 import org.netbeans.junit.MockServices;
35 import org.netbeans.junit.NbTestCase;
36 import org.netbeans.spi.java.classpath.support.ClassPathSupport;
37 import org.netbeans.spi.java.queries.SourceForBinaryQueryImplementation;
38 import org.openide.filesystems.FileObject;
39 import org.netbeans.spi.java.classpath.ClassPathFactory;
40 import org.netbeans.spi.java.classpath.ClassPathImplementation;
41 import org.netbeans.spi.java.classpath.FilteringPathResourceImplementation;
42 import org.netbeans.spi.java.classpath.support.PathResourceBase;
43 import org.openide.filesystems.FileStateInvalidException;
44 import org.openide.filesystems.FileUtil;
45 import org.openide.util.Lookup;
46
47 /**
48  * Test functionality of GlobalPathRegistry.
49  * @author Jesse Glick
50  */

51 public class GlobalPathRegistryTest extends NbTestCase {
52     
53     public GlobalPathRegistryTest(String JavaDoc name) {
54         super(name);
55         MockServices.setServices(SFBQImpl.class, DeadLockSFBQImpl.class);
56     }
57     
58     private GlobalPathRegistry r;
59     private FileObject root;
60     private ClassPath cp1, cp2, cp3, cp4, cp5;
61     protected void setUp() throws Exception JavaDoc {
62         super.setUp();
63         r = GlobalPathRegistry.getDefault();
64         r.clear();
65         clearWorkDir();
66         root = FileUtil.toFileObject(getWorkDir());
67         cp1 = ClassPathSupport.createClassPath(new FileObject[] {root.createFolder("1")});
68         cp2 = ClassPathSupport.createClassPath(new FileObject[] {root.createFolder("2")});
69         cp3 = ClassPathSupport.createClassPath(new FileObject[] {root.createFolder("3")});
70         cp4 = ClassPathSupport.createClassPath(new FileObject[] {root.createFolder("4")});
71         cp5 = ClassPathSupport.createClassPath(new FileObject[] {root.createFolder("5")});
72     }
73     
74     public void testBasicOperation() throws Exception JavaDoc {
75         assertEquals("initially no paths of type a", Collections.<ClassPath>emptySet(), r.getPaths("a"));
76         r.register("a", new ClassPath[] {cp1, cp2});
77         assertEquals("added some paths of type a", new HashSet JavaDoc<ClassPath>(Arrays.asList(new ClassPath[] {cp1, cp2})), r.getPaths("a"));
78         r.register("a", new ClassPath[0]);
79         assertEquals("did not add any new paths to a", new HashSet JavaDoc<ClassPath>(Arrays.asList(new ClassPath[] {cp1, cp2})), r.getPaths("a"));
80         assertEquals("initially no paths of type b", Collections.<ClassPath>emptySet(), r.getPaths("b"));
81         r.register("b", new ClassPath[] {cp3, cp4, cp5});
82         assertEquals("added some paths of type b", new HashSet JavaDoc<ClassPath>(Arrays.asList(new ClassPath[] {cp3, cp4, cp5})), r.getPaths("b"));
83         r.unregister("a", new ClassPath[] {cp1});
84         assertEquals("only one path left of type a", Collections.<ClassPath>singleton(cp2), r.getPaths("a"));
85         r.register("a", new ClassPath[] {cp2, cp3});
86         assertEquals("only one new path added of type a", new HashSet JavaDoc<ClassPath>(Arrays.asList(new ClassPath[] {cp2, cp3})), r.getPaths("a"));
87         r.unregister("a", new ClassPath[] {cp2});
88         assertEquals("still have extra cp2 in a", new HashSet JavaDoc<ClassPath>(Arrays.asList(new ClassPath[] {cp2, cp3})), r.getPaths("a"));
89         r.unregister("a", new ClassPath[] {cp2});
90         assertEquals("last cp2 removed from a", Collections.<ClassPath>singleton(cp3), r.getPaths("a"));
91         r.unregister("a", new ClassPath[] {cp3});
92         assertEquals("a now empty", Collections.<ClassPath>emptySet(), r.getPaths("a"));
93         r.unregister("a", new ClassPath[0]);
94         assertEquals("a still empty", Collections.<ClassPath>emptySet(), r.getPaths("a"));
95         try {
96             r.unregister("a", new ClassPath[] {cp3});
97             fail("should not have been permitted to unregister a nonexistent entry");
98         } catch (IllegalArgumentException JavaDoc x) {
99             // Good.
100
}
101     }
102     
103     public void testListening() throws Exception JavaDoc {
104         assertEquals("initially no paths of type b", Collections.<ClassPath>emptySet(), r.getPaths("b"));
105         L JavaDoc l = new L JavaDoc();
106         r.addGlobalPathRegistryListener(l);
107         r.register("b", new ClassPath[] {cp1, cp2});
108         GlobalPathRegistryEvent e = l.event();
109         assertNotNull("got an event", e);
110         assertTrue("was an addition", l.added());
111         assertEquals("right registry", r, e.getRegistry());
112         assertEquals("right ID", "b", e.getId());
113         assertEquals("right changed paths", new HashSet JavaDoc<ClassPath>(Arrays.asList(new ClassPath[] {cp1, cp2})), e.getChangedPaths());
114         r.register("b", new ClassPath[] {cp2, cp3});
115         e = l.event();
116         assertNotNull("got an event", e);
117         assertTrue("was an addition", l.added());
118         assertEquals("right changed paths", Collections.<ClassPath>singleton(cp3), e.getChangedPaths());
119         r.register("b", new ClassPath[] {cp3});
120         e = l.event();
121         assertNull("no event for adding a dupe", e);
122         r.unregister("b", new ClassPath[] {cp1, cp3, cp3});
123         e = l.event();
124         assertNotNull("got an event", e);
125         assertFalse("was a removal", l.added());
126         assertEquals("right changed paths", new HashSet JavaDoc<ClassPath>(Arrays.asList(new ClassPath[] {cp1, cp3})), e.getChangedPaths());
127         r.unregister("b", new ClassPath[] {cp2});
128         e = l.event();
129         assertNull("no event for removing an extra", e);
130         r.unregister("b", new ClassPath[] {cp2});
131         e = l.event();
132         assertNotNull("now an event for removing the last copy", e);
133         assertFalse("was a removal", l.added());
134         assertEquals("right changed paths", Collections.<ClassPath>singleton(cp2), e.getChangedPaths());
135     }
136     
137     
138     public void testGetSourceRoots () throws Exception JavaDoc {
139         SFBQImpl query = Lookup.getDefault().lookup(SFBQImpl.class);
140         assertNotNull ("SourceForBinaryQueryImplementation not found in lookup",query);
141         query.addPair(cp3.getRoots()[0].getURL(),new FileObject[0]);
142         ClassPathTest.TestClassPathImplementation cpChangingImpl = new ClassPathTest.TestClassPathImplementation();
143         ClassPath cpChanging = ClassPathFactory.createClassPath(cpChangingImpl);
144         assertEquals("cpChangingImpl is empty", 0, cpChanging.getRoots().length);
145         r.register(ClassPath.SOURCE, new ClassPath[] {cp1, cp2, cpChanging});
146         r.register (ClassPath.COMPILE, new ClassPath[] {cp3});
147         Set JavaDoc<FileObject> result = r.getSourceRoots();
148         assertEquals ("Wrong number of source roots",result.size(),cp1.getRoots().length + cp2.getRoots().length);
149         assertTrue ("Missing roots from cp1",result.containsAll (Arrays.asList(cp1.getRoots())));
150         assertTrue ("Missing roots from cp2",result.containsAll (Arrays.asList(cp2.getRoots())));
151         // simulate classpath change:
152
URL JavaDoc u = cp5.entries().get(0).getURL();
153         cpChangingImpl.addResource(u);
154         assertEquals("cpChangingImpl is not empty", 1, cpChanging.getRoots().length);
155         result = r.getSourceRoots();
156         assertEquals ("Wrong number of source roots",result.size(),cp1.getRoots().length + cp2.getRoots().length + cpChanging.getRoots().length);
157         assertTrue ("Missing roots from cp1",result.containsAll (Arrays.asList(cp1.getRoots())));
158         assertTrue ("Missing roots from cp2",result.containsAll (Arrays.asList(cp2.getRoots())));
159         cpChangingImpl.removeResource(u);
160         
161         query.addPair(cp3.getRoots()[0].getURL(),cp4.getRoots());
162         result = r.getSourceRoots();
163         assertEquals ("Wrong number of source roots",result.size(),cp1.getRoots().length + cp2.getRoots().length+cp4.getRoots().length);
164         assertTrue ("Missing roots from cp1",result.containsAll (Arrays.asList(cp1.getRoots())));
165         assertTrue ("Missing roots from cp2",result.containsAll (Arrays.asList(cp2.getRoots())));
166         assertTrue ("Missing roots from cp4",result.containsAll (Arrays.asList(cp4.getRoots())));
167     }
168     
169     /**
170      * Tests issue: #60976:Deadlock between JavaFastOpen$Evaluator and AntProjectHelper$something
171      */

172     public void testGetSourceRootsDeadLock () throws Exception JavaDoc {
173         DeadLockSFBQImpl query = Lookup.getDefault().lookup(DeadLockSFBQImpl.class);
174         assertNotNull ("SourceForBinaryQueryImplementation not found in lookup",query);
175         r.register (ClassPath.COMPILE, new ClassPath[] {cp1});
176         try {
177             query.setSynchronizedJob (
178                 new Runnable JavaDoc () {
179                     public void run () {
180                         r.register(ClassPath.COMPILE, new ClassPath[] {cp2});
181                     }
182                 }
183             );
184             r.getSourceRoots();
185         } finally {
186             query.setSynchronizedJob (null);
187         }
188     }
189
190     public void testFindResource() throws Exception JavaDoc {
191         final FileObject src1 = root.createFolder("src1");
192         FileObject src1included = FileUtil.createData(src1, "included/file");
193         FileUtil.createData(src1, "excluded/file1");
194         FileUtil.createData(src1, "excluded/file2");
195         FileObject src2 = root.createFolder("src2");
196         FileObject src2included = FileUtil.createData(src2, "included/file");
197         FileObject src2excluded1 = FileUtil.createData(src2, "excluded/file1");
198         class PRI extends PathResourceBase implements FilteringPathResourceImplementation {
199             public URL JavaDoc[] getRoots() {
200                 try {
201                     return new URL JavaDoc[] {src1.getURL()};
202                 } catch (FileStateInvalidException x) {
203                     throw new AssertionError JavaDoc(x);
204                 }
205             }
206             public boolean includes(URL JavaDoc root, String JavaDoc resource) {
207                 return resource.startsWith("incl");
208             }
209             public ClassPathImplementation getContent() {
210                 return null;
211             }
212         }
213         r.register(ClassPath.SOURCE, new ClassPath[] {
214             ClassPathSupport.createClassPath(Collections.singletonList(new PRI())),
215             ClassPathSupport.createClassPath(new FileObject[] {src2})
216         });
217         assertTrue(Arrays.asList(src1included, src2included).contains(r.findResource("included/file")));
218         assertEquals(src2excluded1, r.findResource("excluded/file1"));
219         assertEquals(null, r.findResource("excluded/file2"));
220         assertEquals(null, r.findResource("nonexistent"));
221     }
222     
223     private static final class L implements GlobalPathRegistryListener {
224         
225         private GlobalPathRegistryEvent e;
226         private boolean added;
227         
228         public L() {}
229         
230         public synchronized GlobalPathRegistryEvent event() {
231             GlobalPathRegistryEvent _e = e;
232             e = null;
233             return _e;
234         }
235         
236         public boolean added() {
237             return added;
238         }
239         
240         public synchronized void pathsAdded(GlobalPathRegistryEvent e) {
241             assertNull("checked for last event", this.e);
242             this.e = e;
243             added = true;
244         }
245         
246         public synchronized void pathsRemoved(GlobalPathRegistryEvent e) {
247             assertNull("checked for last event", this.e);
248             this.e = e;
249             added = false;
250         }
251         
252     }
253     
254     
255     public static class SFBQImpl implements SourceForBinaryQueryImplementation {
256         
257         private Map JavaDoc<URL JavaDoc,SourceForBinaryQuery.Result> pairs = new HashMap JavaDoc<URL JavaDoc,SourceForBinaryQuery.Result> ();
258         
259         void addPair (URL JavaDoc binaryRoot, FileObject[] sourceRoots) {
260             assert binaryRoot != null && sourceRoots != null;
261             Result r = (Result) this.pairs.get (binaryRoot);
262             if (r == null) {
263                 r = new Result (sourceRoots);
264                 this.pairs.put (binaryRoot, r);
265             }
266             else {
267                 r.setSources(sourceRoots);
268             }
269         }
270                         
271         public SourceForBinaryQuery.Result findSourceRoots(URL JavaDoc binaryRoot) {
272             Result result = (Result) this.pairs.get (binaryRoot);
273             return result;
274         }
275         
276         
277         private static class Result implements SourceForBinaryQuery.Result {
278             
279             private FileObject[] sources;
280             private ArrayList JavaDoc<ChangeListener JavaDoc> listeners = new ArrayList JavaDoc<ChangeListener JavaDoc> ();
281             
282             public Result (FileObject[] sources) {
283                 this.sources = sources;
284             }
285             
286             
287             void setSources (FileObject[] sources) {
288                 this.sources = sources;
289                 this.fireChange ();
290             }
291                         
292             public synchronized void addChangeListener(javax.swing.event.ChangeListener JavaDoc l) {
293                 this.listeners.add (l);
294             }
295             
296             public FileObject[] getRoots() {
297                 return this.sources;
298             }
299             
300             public synchronized void removeChangeListener(javax.swing.event.ChangeListener JavaDoc l) {
301                 this.listeners.remove (l);
302             }
303             
304             private void fireChange () {
305                 Iterator JavaDoc it;
306                 synchronized (this) {
307                     it = ((ArrayList JavaDoc)this.listeners.clone()).iterator();
308                 }
309                 ChangeEvent JavaDoc e = new ChangeEvent JavaDoc (this);
310                 while (it.hasNext()) {
311                     ((ChangeListener JavaDoc)it.next()).stateChanged(e);
312                 }
313             }
314             
315         }
316         
317     }
318     
319     public static class DeadLockSFBQImpl extends Thread JavaDoc implements SourceForBinaryQueryImplementation {
320         
321         private Runnable JavaDoc r;
322         
323         public SourceForBinaryQuery.Result findSourceRoots(URL JavaDoc binaryRoot) {
324             if (this.r != null) {
325                 synchronized (this) {
326                     this.start();
327                     try {
328                         this.wait ();
329                     } catch (InterruptedException JavaDoc ie) {
330                         ie.printStackTrace();
331                     }
332                 }
333             }
334             return null;
335         }
336         
337         public synchronized void run () {
338             r.run();
339             this.notify();
340         }
341         
342         public void setSynchronizedJob (Runnable JavaDoc r) {
343             this.r = r;
344         }
345         
346     }
347     
348 }
349
Popular Tags