1 19 package org.netbeans.api.java.source; 20 21 import java.io.File ; 22 import java.io.IOException ; 23 import java.lang.ref.Reference ; 24 import java.lang.ref.WeakReference ; 25 import java.net.MalformedURLException ; 26 import java.net.URL ; 27 import java.util.ArrayList ; 28 import java.util.Arrays ; 29 import java.util.Collections ; 30 import java.util.HashMap ; 31 import java.util.List ; 32 import java.util.Map ; 33 import java.util.concurrent.CountDownLatch ; 34 import java.util.logging.Handler ; 35 import java.util.logging.Level ; 36 import java.util.logging.LogRecord ; 37 import java.util.logging.Logger ; 38 import org.netbeans.api.java.classpath.ClassPath; 39 import org.netbeans.api.java.source.CancellableTask; 40 import org.netbeans.api.java.source.CompilationInfo; 41 import org.netbeans.api.java.source.JavaSource; 42 import org.netbeans.api.java.source.JavaSource.Priority; 43 import org.netbeans.api.java.source.JavaSourceTaskFactory; 44 import org.netbeans.api.java.source.JavaSource.Phase; 45 import org.netbeans.api.java.source.SourceUtilsTestUtil; 46 import org.netbeans.junit.NbTestCase; 47 import org.netbeans.modules.java.JavaDataLoader; 48 import org.netbeans.modules.java.source.JavaSourceTaskFactoryManager; 49 import org.netbeans.spi.java.classpath.ClassPathProvider; 50 import org.netbeans.spi.java.classpath.support.ClassPathSupport; 51 import org.openide.filesystems.FileObject; 52 import org.openide.filesystems.FileUtil; 53 import org.openide.util.Lookup; 54 import org.openide.util.lookup.ProxyLookup; 55 56 60 public class JavaSourceTaskFactoryTest extends NbTestCase { 61 62 public JavaSourceTaskFactoryTest(String testName) { 63 super(testName); 64 } 65 66 private List <FileObject> files; 67 private List <FileObject> filesWithTasks = new ArrayList <FileObject>(); 68 private Map <FileObject, CancellableTask<CompilationInfo>> file2Task = new HashMap (); 69 70 private Map <FileObject, CancellableTask<CompilationInfo>> addedTasks = new HashMap <FileObject, CancellableTask<CompilationInfo>>(); 71 private Map <FileObject, CancellableTask<CompilationInfo>> removedTasks = new HashMap <FileObject, CancellableTask<CompilationInfo>>(); 72 private Map <FileObject, CancellableTask<CompilationInfo>> rescheduled = new HashMap <FileObject, CancellableTask<CompilationInfo>>(); 73 74 private FileObject testDir; 75 private FileObject testFile1; 76 private FileObject testFile2; 77 private DummyCancellableTask<CompilationInfo> task1; 78 private DummyCancellableTask<CompilationInfo> task2; 79 80 private JavaSourceTaskFactoryImplImpl jstf; 81 private ClassPathProvider cpp; 82 83 private Lookup.Result<JavaSourceTaskFactory> factories; 84 85 protected void setUp() throws Exception { 86 cpp = new ClassPathProvider() { 87 public ClassPath findClassPath(FileObject file, String type) { 88 if (type == ClassPath.SOURCE) 89 return ClassPathSupport.createClassPath(new FileObject[] {FileUtil.toFileObject(getDataDir())}); 90 if (type == ClassPath.COMPILE) 91 return ClassPathSupport.createClassPath(new FileObject[0]); 92 if (type == ClassPath.BOOT) 93 return createBootPath(); 94 return null; 95 } 96 }; 97 SourceUtilsTestUtil.setLookup(new Object [] { 98 JavaDataLoader.getLoader(JavaDataLoader.class), 99 cpp 100 }, this.getClass().getClassLoader()); 101 102 JavaSourceTaskFactoryManager.register(); 103 104 jstf = new JavaSourceTaskFactoryImplImpl(); 105 JavaSourceTaskFactory.ACCESSOR2 = new AccessorImpl(); 106 testDir = SourceUtilsTestUtil.makeScratchDir(this); 107 testFile1 = testDir.createData("test1.java"); 108 testFile2 = testDir.createData("test2.java"); 109 task1 = new DummyCancellableTask<CompilationInfo>(); 110 task2 = new DummyCancellableTask<CompilationInfo>(); 111 112 file2Task.put(testFile1, task1); 113 file2Task.put(testFile1, task2); 114 115 assertNotNull(JavaSource.forFileObject(testFile1)); 116 assertNotNull(JavaSource.forFileObject(testFile2)); 117 } 118 119 public void testTasksRegistration() throws Exception { 120 JavaSourceTaskFactory.SYNCHRONOUS_EVENTS = true; 121 122 files = Arrays.asList(testFile1); 123 124 SourceUtilsTestUtil.setLookup(new Object [] { 125 JavaDataLoader.getLoader(JavaDataLoader.class), 126 jstf, 127 cpp 128 }, this.getClass().getClassLoader()); 129 130 assertEquals(1, addedTasks.size()); 131 assertEquals(testFile1, addedTasks.keySet().iterator().next()); 132 assertEquals(file2Task.get(testFile1), addedTasks.values().iterator().next()); 133 134 assertEquals(0, removedTasks.size()); 135 136 files = Arrays.asList(testFile2); 137 138 addedTasks.clear(); 139 140 jstf.fireChangeEvent(); 141 142 assertEquals(1, removedTasks.size()); 143 assertEquals(testFile1, removedTasks.keySet().iterator().next()); 144 assertEquals(file2Task.get(testFile1), removedTasks.values().iterator().next()); 145 146 assertEquals(1, addedTasks.size()); 147 assertEquals(testFile2, addedTasks.keySet().iterator().next()); 148 assertEquals(file2Task.get(testFile2), addedTasks.values().iterator().next()); 149 150 files = Collections.emptyList(); 151 152 addedTasks.clear(); 153 removedTasks.clear(); 154 155 jstf.fireChangeEvent(); 156 157 assertEquals(1, removedTasks.size()); 158 assertEquals(testFile2, removedTasks.keySet().iterator().next()); 159 assertEquals(file2Task.get(testFile2), removedTasks.values().iterator().next()); 160 161 assertEquals(0, addedTasks.size()); 162 163 files = Arrays.asList(testFile1); 164 165 addedTasks.clear(); 166 removedTasks.clear(); 167 168 jstf.fireChangeEvent(); 169 170 assertEquals(1, addedTasks.size()); 171 assertEquals(testFile1, addedTasks.keySet().iterator().next()); 172 assertEquals(file2Task.get(testFile1), addedTasks.values().iterator().next()); 173 174 assertEquals(0, removedTasks.size()); 175 176 files = Collections.emptyList(); 177 178 addedTasks.clear(); 179 removedTasks.clear(); 180 181 jstf.fireChangeEvent(); 182 183 assertEquals(1, removedTasks.size()); 184 assertEquals(testFile1, removedTasks.keySet().iterator().next()); 185 assertEquals(file2Task.get(testFile1), removedTasks.values().iterator().next()); 186 187 assertEquals(0, addedTasks.size()); 188 } 189 190 public void testTasksRescheduling() throws Exception { 191 files = Arrays.asList(testFile1); 192 193 SourceUtilsTestUtil.setLookup(new Object [] { 194 JavaDataLoader.getLoader(JavaDataLoader.class), 195 jstf, 196 cpp 197 }, this.getClass().getClassLoader()); 198 199 assertEquals(1, addedTasks.size()); 200 assertEquals(testFile1, addedTasks.keySet().iterator().next()); 201 assertEquals(file2Task.get(testFile1), addedTasks.values().iterator().next()); 202 203 jstf.reschedule(testFile1); 204 205 assertEquals(1, rescheduled.size()); 206 assertEquals(testFile1, rescheduled.keySet().iterator().next()); 207 assertEquals(file2Task.get(testFile1), rescheduled.values().iterator().next()); 208 209 } 217 218 public void testFileIsReclaimable() throws Exception { 219 Reference fileRef = new WeakReference (testFile1); 220 Reference jsRef = new WeakReference (JavaSource.forFileObject(testFile1)); 221 files = Arrays.asList(testFile1); 222 223 SourceUtilsTestUtil.setLookup(new Object [] { 224 JavaDataLoader.getLoader(JavaDataLoader.class), 225 jstf, 226 }, this.getClass().getClassLoader()); 227 228 assertEquals(1, addedTasks.size()); 229 assertEquals(testFile1, addedTasks.keySet().iterator().next()); 230 assertEquals(file2Task.get(testFile1), addedTasks.values().iterator().next()); 231 232 files = Collections.emptyList(); 233 234 jstf.fireChangeEvent(); 235 236 filesWithTasks.clear(); 237 file2Task.clear(); 238 239 addedTasks.clear(); 240 removedTasks.clear(); 241 rescheduled.clear(); 242 243 testDir = null; 244 testFile1 = null; 245 testFile2 = null; 246 task1 = null; 247 task2 = null; 248 249 assertGC("", fileRef); 250 assertGC("", jsRef); 251 } 252 253 public void testDeadlock88782() throws Exception { 254 files = Collections.emptyList(); 255 256 SourceUtilsTestUtil.setLookup(new Object [] { 257 JavaDataLoader.getLoader(JavaDataLoader.class), 258 jstf, 259 cpp 260 }, this.getClass().getClassLoader()); 261 262 final CountDownLatch l = new CountDownLatch (2); 263 final Object lock = new Object (); 264 265 Logger.getLogger(JavaSourceTaskFactory.class.getName()).setLevel(Level.FINEST); 266 267 Logger.getLogger(JavaSourceTaskFactory.class.getName()).addHandler(new Handler () { 268 public void publish(LogRecord record) { 269 if (JavaSourceTaskFactory.BEFORE_ADDING_REMOVING_TASKS.equals(record.getMessage())) { 270 l.countDown(); 271 try { 272 l.await(); 273 } catch (InterruptedException e) { 274 Logger.global.log(Level.SEVERE, "", e); 275 } 276 synchronized (lock) { 277 } 278 } 279 if (JavaSourceTaskFactory.FILEOBJECTS_COMPUTATION.equals(record.getMessage())) { 280 l.countDown(); 281 try { 282 l.await(); 283 } catch (InterruptedException e) { 284 Logger.global.log(Level.SEVERE, "", e); 285 } 286 } 287 } 288 public void flush() {} 289 public void close() throws SecurityException {} 290 }); 291 292 Thread t1 = new Thread () { 293 public void run() { 294 synchronized (lock) { 295 SourceUtilsTestUtil.setLookup(new Object [] { 296 JavaDataLoader.getLoader(JavaDataLoader.class), 297 jstf, 298 new JavaSourceTaskFactoryImplImpl(), 299 cpp 300 }, this.getClass().getClassLoader()); 301 } 302 } 303 }; 304 305 t1.start(); 306 307 Thread t2 = new Thread () { 308 public void run() { 309 jstf.fireChangeEvent(); 310 } 311 }; 312 313 t2.start(); 314 315 t1.join(); 316 t2.join(); 317 } 318 319 private ClassPath createBootPath () { 320 try { 321 String bootPath = System.getProperty ("sun.boot.class.path"); 322 String [] paths = bootPath.split(File.pathSeparator); 323 List <URL >roots = new ArrayList <URL > (paths.length); 324 for (String path : paths) { 325 File f = new File (path); 326 if (!f.exists()) { 327 continue; 328 } 329 URL url = f.toURI().toURL(); 330 if (FileUtil.isArchiveFile(url)) { 331 url = FileUtil.getArchiveRoot(url); 332 } 333 roots.add (url); 334 } 335 return ClassPathSupport.createClassPath(roots.toArray(new URL [roots.size()])); 336 } catch (MalformedURLException ex) {} 337 return null; 338 } 339 340 private class AccessorImpl implements JavaSourceTaskFactory.Accessor2 { 341 342 public void addPhaseCompletionTask(JavaSource js, CancellableTask<CompilationInfo> task, Phase phase, Priority priority) throws IOException { 343 addedTasks.put(js.getFileObjects().iterator().next(), task); 344 } 345 346 public void removePhaseCompletionTask(JavaSource js, CancellableTask<CompilationInfo> task) { 347 removedTasks.put(js.getFileObjects().iterator().next(), task); 348 } 349 350 public void rescheduleTask(JavaSource js, CancellableTask<CompilationInfo> task) { 351 rescheduled.put(js.getFileObjects().iterator().next(), task); 352 } 353 354 } 355 356 private static class DummyCancellableTask<CompilationInfo> implements CancellableTask<CompilationInfo> { 357 358 public void cancel() { 359 } 360 361 public void run(CompilationInfo parameter) { 362 } 363 364 } 365 366 private class JavaSourceTaskFactoryImplImpl extends JavaSourceTaskFactory { 367 public JavaSourceTaskFactoryImplImpl() { 368 super(Phase.UP_TO_DATE, Priority.MAX); 369 } 370 371 public CancellableTask<CompilationInfo> createTask(FileObject file) { 372 filesWithTasks.add(file); 373 return file2Task.get(file); 374 } 375 376 public synchronized List <FileObject> getFileObjects() { 377 return files; 378 } 379 380 private void fireChangeEvent() { 381 super.fileObjectsChanged(); 382 } 383 384 } 385 386 private static class ChangeableLookup extends ProxyLookup { 387 388 public void setLookupsImpl(Lookup[] lookups) { 389 setLookups(lookups); 390 } 391 } 392 393 } 394 | Popular Tags |