KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > java > source > usages > RepositoryUpdater


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.usages;
21
22 import com.sun.source.tree.CompilationUnitTree;
23 import com.sun.source.tree.Tree;
24 import com.sun.source.util.TaskEvent;
25 import com.sun.source.util.TaskListener;
26 import com.sun.tools.javac.api.JavacTaskImpl;
27 import com.sun.tools.javac.api.JavacTaskImpl.Filter;
28 import com.sun.tools.javac.code.Symbol;
29 import com.sun.tools.javac.code.Symbol.ClassSymbol;
30 import com.sun.tools.javac.comp.AttrContext;
31 import com.sun.tools.javac.comp.Env;
32 import com.sun.tools.javac.main.JavaCompiler;
33 import com.sun.tools.javac.tree.JCTree;
34 import com.sun.tools.javac.util.Log;
35 import com.sun.tools.javac.util.Abort;
36 import com.sun.tools.javac.util.CouplingAbort;
37 import java.beans.PropertyChangeEvent JavaDoc;
38 import java.beans.PropertyChangeListener JavaDoc;
39 import java.io.BufferedReader JavaDoc;
40 import java.io.File JavaDoc;
41 import java.io.FileOutputStream JavaDoc;
42 import java.io.FileReader JavaDoc;
43 import java.io.IOException JavaDoc;
44 import java.io.OutputStream JavaDoc;
45 import java.io.OutputStreamWriter JavaDoc;
46 import java.io.PrintWriter JavaDoc;
47 import java.net.URI JavaDoc;
48 import java.net.URL JavaDoc;
49 import java.util.ArrayList JavaDoc;
50 import java.util.Collections JavaDoc;
51 import java.util.HashMap JavaDoc;
52 import java.util.HashSet JavaDoc;
53 import java.util.Iterator JavaDoc;
54 import java.util.LinkedList JavaDoc;
55 import java.util.List JavaDoc;
56 import java.util.Map JavaDoc;
57 import java.util.Set JavaDoc;
58 import java.util.Stack JavaDoc;
59 import java.util.StringTokenizer JavaDoc;
60 import java.util.Timer JavaDoc;
61 import java.util.TimerTask JavaDoc;
62 import java.util.TooManyListenersException JavaDoc;
63 import java.util.concurrent.CountDownLatch JavaDoc;
64 import java.util.concurrent.atomic.AtomicBoolean JavaDoc;
65 import java.util.logging.Level JavaDoc;
66 import java.util.logging.Logger JavaDoc;
67 import javax.lang.model.element.TypeElement;
68 import javax.lang.model.type.ErrorType;
69 import javax.swing.event.ChangeEvent JavaDoc;
70 import javax.swing.event.ChangeListener JavaDoc;
71 import javax.tools.DiagnosticListener;
72 import javax.tools.Diagnostic;
73 import javax.tools.JavaFileManager;
74 import javax.tools.JavaFileObject;
75 import javax.tools.StandardLocation;
76 import org.netbeans.api.java.classpath.ClassPath;
77 import org.netbeans.api.java.queries.SourceLevelQuery;
78 import org.netbeans.api.java.source.CancellableTask;
79 import org.netbeans.api.java.source.ClasspathInfo;
80 import org.netbeans.api.java.source.CompilationInfo;
81 import org.netbeans.api.java.source.JavaSource;
82 import org.netbeans.api.progress.ProgressHandle;
83 import org.netbeans.api.progress.ProgressHandleFactory;
84 import org.netbeans.api.queries.VisibilityQuery;
85 import org.netbeans.modules.java.JavaDataLoader;
86 import org.netbeans.modules.java.source.*;
87 import org.netbeans.modules.java.source.JavaFileFilterQuery;
88 import org.netbeans.modules.java.source.classpath.CacheClassPath;
89 import org.netbeans.modules.java.source.classpath.GlobalSourcePath;
90 import org.netbeans.modules.java.source.parsing.*;
91 import org.netbeans.modules.java.source.parsing.FileObjects;
92 import org.netbeans.modules.java.preprocessorbridge.spi.JavaFileFilterImplementation;
93 import org.netbeans.modules.java.source.util.LowMemoryEvent;
94 import org.netbeans.modules.java.source.util.LowMemoryListener;
95 import org.netbeans.modules.java.source.util.LowMemoryNotifier;
96 import org.netbeans.spi.java.classpath.ClassPathFactory;
97 import org.openide.filesystems.FileAttributeEvent;
98 import org.openide.filesystems.FileChangeListener;
99 import org.openide.filesystems.FileEvent;
100 import org.openide.filesystems.FileObject;
101 import org.openide.filesystems.FileRenameEvent;
102 import org.openide.filesystems.FileStateInvalidException;
103 import org.openide.filesystems.FileSystem;
104 import org.openide.filesystems.FileUtil;
105 import org.openide.filesystems.URLMapper;
106 import org.openide.util.Exceptions;
107 import org.openide.util.NbBundle;
108 import org.openide.util.TopologicalSortException;
109 import org.openide.util.Utilities;
110
111 /**
112  *
113  * @author Tomas Zezula
114  */

115 public class RepositoryUpdater implements PropertyChangeListener JavaDoc, FileChangeListener {
116         
117     private static final Logger JavaDoc LOGGER = Logger.getLogger(RepositoryUpdater.class.getName());
118     private static final Set JavaDoc<String JavaDoc> ignoredDirectories = parseSet("org.netbeans.javacore.ignoreDirectories", "SCCS CVS .svn"); // NOI18N
119
private static final boolean noscan = Boolean.getBoolean("netbeans.javacore.noscan"); //NOI18N
120
public static final boolean PERF_TEST = Boolean.getBoolean("perf.refactoring.test");
121     private static final String JavaDoc PACKAGE_INFO = "package-info.java"; //NOI18N
122

123     private static final int DELAY = Utilities.isWindows() ? 2000 : 1000;
124     
125     private static RepositoryUpdater instance;
126     
127     private final GlobalSourcePath cpImpl;
128     private final ClassPath cp;
129     private final ClassPath ucp;
130     private final ClassPath binCp;
131     private Set JavaDoc<URL JavaDoc> scannedRoots;
132     private Set JavaDoc<URL JavaDoc> scannedBinaries;
133     private Delay delay;
134     private Work currentWork;
135     private boolean dirty;
136     private int noSubmited;
137     
138     //Preprocessor support
139
private final Map JavaDoc<URL JavaDoc, JavaFileFilterImplementation> filters = Collections.synchronizedMap(new HashMap JavaDoc<URL JavaDoc, JavaFileFilterImplementation>());
140     private final FilterListener filterListener = new FilterListener ();
141     
142     /** Creates a new instance of RepositoryUpdater */
143     private RepositoryUpdater() {
144         try {
145             this.scannedRoots = Collections.synchronizedSet(new HashSet JavaDoc<URL JavaDoc>());
146             this.scannedBinaries = Collections.synchronizedSet(new HashSet JavaDoc<URL JavaDoc>());
147             this.delay = new Delay();
148             this.cpImpl = GlobalSourcePath.getDefault();
149             this.cpImpl.setExcludesListener (this);
150             this.cp = ClassPathFactory.createClassPath (this.cpImpl.getSourcePath());
151             this.cp.addPropertyChangeListener(this);
152             this.ucp = ClassPathFactory.createClassPath (this.cpImpl.getUnknownSourcePath());
153             this.binCp = ClassPathFactory.createClassPath(this.cpImpl.getBinaryPath());
154             this.registerFileSystemListener();
155             submitBatch();
156         } catch (TooManyListenersException JavaDoc e) {
157             throw new IllegalStateException JavaDoc ();
158         }
159     }
160     
161     public ClassPath getScannedSources () {
162         return this.cp;
163     }
164     
165     public ClassPath getScannedBinaries() {
166         return this.binCp;
167     }
168     
169     public void close () {
170         this.cp.removePropertyChangeListener(this);
171         this.unregisterFileSystemListener();
172         this.delay.cancel();
173     }
174
175     public void propertyChange(PropertyChangeEvent JavaDoc evt) {
176         if (ClassPath.PROP_ROOTS.equals(evt.getPropertyName())) {
177             submitBatch();
178         }
179         else if (GlobalSourcePath.PROP_INCLUDES.equals(evt.getPropertyName())) {
180             ClassPath changedCp = (ClassPath) evt.getNewValue();
181             assert changedCp != null;
182             for (ClassPath.Entry e : changedCp.entries()) {
183                 URL JavaDoc root = e.getURL();
184                 scheduleCompilation(root,root, true);
185             }
186         }
187     }
188     
189     private synchronized void submitBatch () {
190         if (this.currentWork == null) {
191             this.currentWork = Work.batch();
192             submit (this.currentWork);
193         }
194         else {
195             this.dirty = true;
196         }
197     }
198     
199     public synchronized boolean isScanInProgress() {
200         return this.noSubmited > 0;
201     }
202     
203     public synchronized void waitScanFinished () throws InterruptedException JavaDoc {
204         while (this.noSubmited > 0 ) {
205             this.wait();
206         }
207     }
208     
209     
210     private synchronized boolean isDirty () {
211         if (this.dirty) {
212             this.dirty = false;
213             return true;
214         }
215         else {
216             this.currentWork = null;
217             return false;
218         }
219     }
220     
221     private synchronized void resetDirty () {
222         this.dirty = false;
223         this.currentWork = null;
224     }
225     
226     
227     public void fileRenamed(FileRenameEvent fe) {
228         final FileObject fo = fe.getFile();
229         try {
230             if ((isJava (fo) || fo.isFolder()) && VisibilityQuery.getDefault().isVisible(fo)) {
231                 final URL JavaDoc root = getOwningSourceRoot(fo);
232                 if (root != null) {
233                     String JavaDoc originalName = fe.getName();
234                     final String JavaDoc originalExt = fe.getExt();
235                     if (originalExt.length()>0) {
236                         originalName = originalName+'.'+originalExt; //NOI18N
237
}
238                     final File JavaDoc parentFile = FileUtil.toFile(fo.getParent());
239                     if (parentFile != null) {
240                         final URL JavaDoc original = new File JavaDoc (parentFile,originalName).toURI().toURL();
241                         submit(Work.delete(original,root,fo.isFolder()));
242                         delay.post(Work.compile (fo,root));
243                     }
244                 }
245             }
246             else if (isBinary(fo) && VisibilityQuery.getDefault().isVisible(fo)) {
247                 final URL JavaDoc root = getOwningBinaryRoot(fo);
248                 if (root != null) {
249                     String JavaDoc originalName = fe.getName();
250                     final String JavaDoc originalExt = fe.getExt();
251                     if (originalExt.length()>0) {
252                         originalName = originalName+'.'+originalExt; //NOI18N
253
}
254                     final File JavaDoc parentFile = FileUtil.toFile(fo.getParent());
255                     if (parentFile != null) {
256                         final URL JavaDoc original = new File JavaDoc (parentFile,originalName).toURI().toURL();
257                         submit(Work.binary(original, root, fo.isFolder()));
258                         submit(Work.binary(fo, root));
259                     }
260                 }
261             }
262         } catch (IOException JavaDoc ioe) {
263             Exceptions.printStackTrace(ioe);
264         }
265     }
266
267     public void fileAttributeChanged(FileAttributeEvent fe) {
268         //Not interesting, do nothing
269
}
270
271     public void fileFolderCreated(FileEvent fe) {
272         //In ideal case this should do nothing,
273
//but in Netbeans newlly created folder may
274
//already contain files
275
final FileObject fo = fe.getFile();
276         try {
277             final URL JavaDoc root = getOwningSourceRoot(fo);
278             if ( root != null && VisibilityQuery.getDefault().isVisible(fo)) {
279                 scheduleCompilation(fo,root);
280             }
281         } catch (IOException JavaDoc ioe) {
282             Exceptions.printStackTrace(ioe);
283         }
284     }
285
286     public void fileDeleted(FileEvent fe) {
287         final FileObject fo = fe.getFile();
288         final boolean isFolder = fo.isFolder();
289         try {
290             if ((isJava(fo) || isFolder) && VisibilityQuery.getDefault().isVisible(fo)) {
291                 final URL JavaDoc root = getOwningSourceRoot (fo);
292                 if (root != null) {
293                     submit(Work.delete(fo,root,isFolder));
294                 }
295             }
296             else if ((isBinary(fo) || isFolder) && VisibilityQuery.getDefault().isVisible(fo)) {
297                 final URL JavaDoc root = getOwningBinaryRoot(fo);
298                 if (root !=null) {
299                     submit(Work.binary(fo,root));
300                 }
301             }
302         } catch (IOException JavaDoc ioe) {
303             Exceptions.printStackTrace(ioe);
304         }
305     }
306
307     public void fileDataCreated(FileEvent fe) {
308         final FileObject fo = fe.getFile();
309         try {
310             if (isJava(fo) && VisibilityQuery.getDefault().isVisible(fo)) {
311                 final URL JavaDoc root = getOwningSourceRoot (fo);
312                 if (root != null) {
313                     postCompilation(fo, root);
314                 }
315             }
316             else if (isBinary(fo) && VisibilityQuery.getDefault().isVisible(fo)) {
317                 final URL JavaDoc root = getOwningBinaryRoot(fo);
318                 if (root != null) {
319                     submit(Work.binary(fo, root));
320                 }
321             }
322         } catch (IOException JavaDoc ioe) {
323             Exceptions.printStackTrace(ioe);
324         }
325     }
326
327     public void fileChanged(FileEvent fe) {
328         final FileObject fo = fe.getFile();
329         try {
330             if (isJava(fo) && VisibilityQuery.getDefault().isVisible(fo)) {
331                 final URL JavaDoc root = getOwningSourceRoot (fo);
332                 if (root != null) {
333                     postCompilation(fo, root);
334                 }
335             }
336             else if (isBinary(fo) && VisibilityQuery.getDefault().isVisible(fo)) {
337                 final URL JavaDoc root = getOwningBinaryRoot(fo);
338                 if (root != null) {
339                     submit(Work.binary(fo, root));
340                 }
341             }
342         } catch (IOException JavaDoc ioe) {
343             Exceptions.printStackTrace(ioe);
344         }
345     }
346     
347     
348     public final void scheduleCompilation (final FileObject fo, final FileObject root) throws IOException JavaDoc {
349         URL JavaDoc foURL = fo.getURL();
350         URL JavaDoc rootURL = root.getURL();
351         assert "file".equals(foURL.getProtocol()) && "file".equals(rootURL.getProtocol());
352         scheduleCompilation (foURL,rootURL,fo.isFolder());
353     }
354     
355     private final void scheduleCompilation (final FileObject fo, final URL JavaDoc root) throws IOException JavaDoc {
356         scheduleCompilation (fo.getURL(),root,fo.isFolder());
357     }
358     
359     private final void scheduleCompilation (final URL JavaDoc file, final URL JavaDoc root, boolean isFolder) {
360         submit(Work.compile (file,root, isFolder));
361     }
362     
363     private final void postCompilation (final FileObject file, final URL JavaDoc root) throws FileStateInvalidException {
364         delay.post (Work.compile (file,root));
365     }
366     
367     
368     /**
369      * This method is only for unit tests.
370      * Test can schedule compilation and wait on the returned {@link CountDownLatch}
371      * until the compilation is finished.
372      * @param folder to be compiled
373      * @param root the source root. The folder has to be either under the root or
374      * equal to the root.
375      * @return {@link CountDownLatch} to wait on.
376      */

377     public final CountDownLatch JavaDoc scheduleCompilationAndWait (final FileObject folder, final FileObject root) throws IOException JavaDoc {
378         CountDownLatch JavaDoc[] latch = new CountDownLatch JavaDoc[1];
379         submit(Work.compile (folder,root.getURL(),latch));
380         return latch[0];
381     }
382     
383     private void submit (final Work work) {
384         if (!noscan) {
385             synchronized (this) {
386                 this.noSubmited++;
387             }
388             final CompileWorker cw = new CompileWorker (work);
389             JavaSourceAccessor.INSTANCE.runSpecialTask (cw,JavaSource.Priority.MAX);
390         }
391     }
392     
393     
394     private void registerFileSystemListener () {
395         final File JavaDoc[] roots = File.listRoots();
396         final Set JavaDoc<FileSystem> fss = new HashSet JavaDoc<FileSystem> ();
397         for (File JavaDoc root : roots) {
398             final FileObject fo = FileUtil.toFileObject (root);
399             if (fo != null) {
400                 try {
401                     final FileSystem fs = fo.getFileSystem();
402                     if (!fss.contains(fs)) {
403                         fs.addFileChangeListener (this);
404                         fss.add(fs);
405                     }
406                 } catch (FileStateInvalidException e) {
407                     Exceptions.printStackTrace(e);
408                 }
409             }
410         }
411     }
412     
413     private void unregisterFileSystemListener () {
414         final File JavaDoc[] roots = File.listRoots();
415         final Set JavaDoc<FileSystem> fss = new HashSet JavaDoc<FileSystem> ();
416         for (File JavaDoc root : roots) {
417             final FileObject fo = FileUtil.toFileObject (root);
418             if (fo != null) {
419                 try {
420                     final FileSystem fs = fo.getFileSystem();
421                     if (!fss.contains(fs)) {
422                         fs.removeFileChangeListener (this);
423                         fss.add(fs);
424                     }
425                 } catch (FileStateInvalidException e) {
426                     Exceptions.printStackTrace(e);
427                 }
428             }
429         }
430     }
431     
432     private URL JavaDoc getOwningSourceRoot (final FileObject fo) {
433         if (fo == null) {
434             return null;
435         }
436         synchronized (this.scannedRoots) {
437             for (URL JavaDoc root : this.scannedRoots) {
438                 FileObject rootFo = URLMapper.findFileObject(root);
439                 if (rootFo != null && FileUtil.isParentOf(rootFo,fo)) {
440                     return root;
441                 }
442             }
443         }
444         return null;
445     }
446     
447     private URL JavaDoc getOwningBinaryRoot (final FileObject fo){
448         if (fo == null) {
449             return null;
450         }
451         try {
452             synchronized (this.scannedBinaries) {
453                 URL JavaDoc foURL = fo.getURL();
454                 for (URL JavaDoc root : this.scannedBinaries) {
455                     URL JavaDoc fileURL = FileUtil.getArchiveFile(root);
456                     boolean archive = true;
457                     if (fileURL == null) {
458                         fileURL = root;
459                         archive = false;
460                     }
461                     String JavaDoc filePath = fileURL.getPath();
462                     String JavaDoc foPath = foURL.getPath();
463                     if (filePath.equals(foPath)) {
464                         return root;
465                     }
466                     if (!archive && foPath.startsWith(filePath)) {
467                         return root;
468                     }
469                 }
470             }
471         } catch (FileStateInvalidException fsi) {
472             Exceptions.printStackTrace(fsi);
473         }
474         return null;
475     }
476     
477     /**
478      * Temporary implementation which does not care about
479      * extended mime types like text/x-something+x-java
480      */

481     private static boolean isJava (final FileObject fo) {
482         if (fo.isFolder()) {
483             return false;
484         }
485         else if (JavaDataLoader.JAVA_EXTENSION.equals(fo.getExt().toLowerCase())) {
486             return true;
487         }
488         else {
489             return JavaDataLoader.JAVA_MIME_TYPE.equals(fo.getMIMEType());
490         }
491     }
492     
493     private static boolean isBinary (final FileObject fo) {
494         if (fo.isFolder()) {
495             return false;
496         }
497         String JavaDoc ext = fo.getExt().toLowerCase();
498         if (FileObjects.CLASS.equals(ext) ||
499             FileObjects.JAR.equals(ext) ||
500             FileObjects.ZIP.equals(ext)) {
501                 return true;
502         }
503         return false;
504     }
505     
506     private static enum WorkType {
507         COMPILE_BATCH, COMPILE_CONT, COMPILE, DELETE, UPDATE_BINARY, FILTER_CHANGED
508     };
509     
510     
511     private static class Work {
512         private final WorkType workType;
513         private final CountDownLatch JavaDoc latch;
514         
515         protected Work (WorkType workType, CountDownLatch JavaDoc latch) {
516             assert workType != null;
517             this.workType = workType;
518             this.latch = latch;
519         }
520         
521         public WorkType getType () {
522             return this.workType;
523         }
524         
525         public void finished () {
526             if (this.latch != null) {
527                 this.latch.countDown();
528             }
529         }
530         
531         
532         public static Work batch () {
533             return new Work (WorkType.COMPILE_BATCH, null);
534         }
535         
536         public static Work compile (final FileObject file, final URL JavaDoc root) throws FileStateInvalidException {
537             return compile (file.getURL(), root, file.isFolder());
538         }
539         
540         public static Work compile (final URL JavaDoc file, final URL JavaDoc root, boolean isFolder) {
541             assert file != null && root != null;
542             return new SingleRootWork (WorkType.COMPILE, file, root, isFolder, null);
543         }
544         
545         public static Work compile (final FileObject file, final URL JavaDoc root, CountDownLatch JavaDoc[] latch) throws FileStateInvalidException {
546             assert file != null && root != null;
547             assert latch != null && latch.length == 1 && latch[0] == null;
548             latch[0] = new CountDownLatch JavaDoc (1);
549             return new SingleRootWork (WorkType.COMPILE, file.getURL(), root, file.isFolder(),latch[0]);
550         }
551         
552         public static Work delete (final FileObject file, final URL JavaDoc root, final boolean isFolder) throws FileStateInvalidException {
553             return delete (file.getURL(), root,file.isFolder());
554         }
555         
556         public static Work delete (final URL JavaDoc file, final URL JavaDoc root, final boolean isFolder) {
557             assert file != null && root != null;
558             return new SingleRootWork (WorkType.DELETE, file, root, isFolder,null);
559         }
560         
561         public static Work binary (final FileObject file, final URL JavaDoc root) throws FileStateInvalidException {
562             return binary (file.getURL(), root, file.isFolder());
563         }
564         
565         public static Work binary (final URL JavaDoc file, final URL JavaDoc root, boolean isFolder) {
566             assert file != null && root != null;
567             return new SingleRootWork (WorkType.UPDATE_BINARY, file, root, isFolder, null);
568         }
569         
570         public static Work filterChange (final List JavaDoc<URL JavaDoc> roots) {
571             assert roots != null;
572             return new MultiRootsWork (WorkType.FILTER_CHANGED, roots, null);
573         }
574         
575     }
576         
577     private static class SingleRootWork extends Work {
578         
579         private URL JavaDoc file;
580         private URL JavaDoc root;
581         private boolean isFolder;
582         
583                 
584         public SingleRootWork (WorkType type, URL JavaDoc file, URL JavaDoc root, boolean isFolder, CountDownLatch JavaDoc latch) {
585             super (type, latch);
586             this.file = file;
587             this.root = root;
588             this.isFolder = isFolder;
589         }
590         
591         public URL JavaDoc getFile () {
592             return this.file;
593         }
594         
595         public URL JavaDoc getRoot () {
596             return this.root;
597         }
598         
599         public boolean isFolder () {
600             return this.isFolder;
601         }
602         
603     }
604     
605     private static class MultiRootsWork extends Work {
606         private List JavaDoc<URL JavaDoc> roots;
607         
608         public MultiRootsWork (WorkType type, List JavaDoc<URL JavaDoc> roots, CountDownLatch JavaDoc latch) {
609             super (type, latch);
610             this.roots = roots;
611         }
612         
613         public List JavaDoc<URL JavaDoc> getRoots () {
614             return roots;
615         }
616     }
617     
618     private final class CompileWorker implements CancellableTask<CompilationInfo> {
619                 
620         private Work work;
621         private List JavaDoc<URL JavaDoc> state;
622         private Set JavaDoc<URL JavaDoc> oldRoots;
623         private Set JavaDoc<URL JavaDoc> oldBinaries;
624         private Set JavaDoc<URL JavaDoc> newBinaries;
625         private ProgressHandle handle;
626         private final Set JavaDoc<URI JavaDoc> dirtyCrossFiles;
627         private final Set JavaDoc<URL JavaDoc> ignoreExcludes;
628         private final AtomicBoolean JavaDoc canceled;
629         
630         public CompileWorker (Work work ) {
631             assert work != null;
632             this.work = work;
633             this.canceled = new AtomicBoolean JavaDoc (false);
634             this.dirtyCrossFiles = new HashSet JavaDoc<URI JavaDoc>();
635             this.ignoreExcludes = new HashSet JavaDoc<URL JavaDoc>();
636         }
637         
638         public void cancel () {
639             this.canceled.set(true);
640         }
641         
642         public void run (final CompilationInfo nullInfo) throws IOException JavaDoc {
643             ClassIndexManager.getDefault().writeLock (new ClassIndexManager.ExceptionAction<Void JavaDoc> () {
644                 
645                 @SuppressWarnings JavaDoc("fallthrough")
646                 public Void JavaDoc run () throws IOException JavaDoc {
647                     boolean continuation = false;
648                     try {
649                     final WorkType type = work.getType();
650                     switch (type) {
651                         case FILTER_CHANGED:
652                             try {
653                                 final MultiRootsWork mw = (MultiRootsWork) work;
654                                 final List JavaDoc<URL JavaDoc> roots = mw.getRoots();
655                                 final Map JavaDoc<URL JavaDoc,List JavaDoc<URL JavaDoc>> depGraph = new HashMap JavaDoc<URL JavaDoc,List JavaDoc<URL JavaDoc>> ();
656                                 for (URL JavaDoc root: roots) {
657                                     findDependencies (root, new Stack JavaDoc<URL JavaDoc>(), depGraph, null, false);
658                                 }
659                                 state = Utilities.topologicalSort(roots, depGraph);
660                                 for (java.util.ListIterator JavaDoc<URL JavaDoc> it = state.listIterator(state.size()); it.hasPrevious(); ) {
661                                     final URL JavaDoc rootURL = it.previous();
662                                     it.remove();
663                                     updateFolder (rootURL,rootURL, true, handle);
664                                 }
665                             } catch (final TopologicalSortException tse) {
666                                     final IllegalStateException JavaDoc ise = new IllegalStateException JavaDoc ();
667                                     throw (IllegalStateException JavaDoc) ise.initCause(tse);
668                             }
669                             break;
670                         case COMPILE_BATCH:
671                         {
672                             assert handle == null;
673                             handle = ProgressHandleFactory.createHandle(NbBundle.getMessage(RepositoryUpdater.class,"MSG_BackgroundCompileStart"));
674                             handle.start();
675                             boolean completed = false;
676                             try {
677                                 oldRoots = new HashSet JavaDoc<URL JavaDoc> (scannedRoots);
678                                 oldBinaries = new HashSet JavaDoc<URL JavaDoc> (scannedBinaries);
679                                 final List JavaDoc<ClassPath.Entry> entries = new LinkedList JavaDoc<ClassPath.Entry>();
680                                 entries.addAll (cp.entries());
681                                 entries.addAll (ucp.entries());
682                                 final List JavaDoc<ClassPath.Entry> binaryEntries = binCp.entries();
683                                 newBinaries = new HashSet JavaDoc<URL JavaDoc> ();
684                                 for (ClassPath.Entry entry : binaryEntries) {
685                                     URL JavaDoc binRoot = entry.getURL();
686                                     if (!oldBinaries.remove(binRoot)) {
687                                         newBinaries.add (binRoot);
688                                     }
689                                 }
690                                 final Map JavaDoc<URL JavaDoc,List JavaDoc<URL JavaDoc>> depGraph = new HashMap JavaDoc<URL JavaDoc,List JavaDoc<URL JavaDoc>> ();
691                                 for (ClassPath.Entry entry : entries) {
692                                     final URL JavaDoc rootURL = entry.getURL();
693                                     findDependencies (rootURL, new Stack JavaDoc<URL JavaDoc>(), depGraph, newBinaries, true);
694                                 }
695                                 CompileWorker.this.state = Utilities.topologicalSort(depGraph.keySet(), depGraph);
696                                 completed = true;
697                             } catch (final TopologicalSortException tse) {
698                                 final IllegalStateException JavaDoc ise = new IllegalStateException JavaDoc ();
699                                 throw (IllegalStateException JavaDoc) ise.initCause(tse);
700                             } finally {
701                                 if (!completed) {
702                                     resetDirty();
703                                 }
704                             }
705                         }
706                         case COMPILE_CONT:
707                             boolean completed = false;
708                             try {
709                                 if (!scanRoots()) {
710                                     CompileWorker.this.work = new Work (WorkType.COMPILE_CONT,null);
711                                     JavaSourceAccessor.INSTANCE.runSpecialTask (CompileWorker.this,JavaSource.Priority.MAX);
712                                     continuation = true;
713                                     return null;
714                                 }
715                                 while (isDirty()) {
716                                     assert CompileWorker.this.state.isEmpty();
717                                     final List JavaDoc<ClassPath.Entry> entries = new LinkedList JavaDoc<ClassPath.Entry>();
718                                     entries.addAll (cp.entries());
719                                     entries.addAll (ucp.entries());
720                                     final List JavaDoc<ClassPath.Entry> binaryEntries = binCp.entries();
721                                     newBinaries = new HashSet JavaDoc<URL JavaDoc> ();
722                                     for (ClassPath.Entry entry : binaryEntries) {
723                                         URL JavaDoc binRoot = entry.getURL();
724                                         if (!scannedBinaries.contains(binRoot)) {
725                                             newBinaries.add(binRoot);
726                                         }
727                                         else {
728                                             oldBinaries.remove(binRoot);
729                                         }
730                                     }
731                                     final Map JavaDoc<URL JavaDoc,List JavaDoc<URL JavaDoc>> depGraph = new HashMap JavaDoc<URL JavaDoc,List JavaDoc<URL JavaDoc>> ();
732                                     for (ClassPath.Entry entry : entries) {
733                                         final URL JavaDoc rootURL = entry.getURL();
734                                         findDependencies (rootURL, new Stack JavaDoc<URL JavaDoc>(), depGraph, newBinaries, true);
735                                     }
736                                     try {
737                                         CompileWorker.this.state = Utilities.topologicalSort(depGraph.keySet(), depGraph);
738                                     } catch (final TopologicalSortException tse) {
739                                         final IllegalStateException JavaDoc ise = new IllegalStateException JavaDoc ();
740                                         throw (IllegalStateException JavaDoc) ise.initCause(tse);
741                                     }
742                                     if (!scanRoots ()) {
743                                         CompileWorker.this.work = new Work (WorkType.COMPILE_CONT,null);
744                                         JavaSourceAccessor.INSTANCE.runSpecialTask (CompileWorker.this,JavaSource.Priority.MAX);
745                                         continuation = true;
746                                         return null;
747                                     }
748                                 }
749                                 completed = true;
750                             } finally {
751                                 if (!completed && !continuation) {
752                                     resetDirty ();
753                                 }
754                             }
755                             final ClassIndexManager cim = ClassIndexManager.getDefault();
756                             scannedRoots.removeAll(oldRoots);
757                             for (URL JavaDoc oldRoot : oldRoots) {
758                                 cim.removeRoot(oldRoot);
759                                 JavaFileFilterImplementation filter = filters.remove(oldRoot);
760                                 if (filter != null && !filters.values().contains(filter)) {
761                                     filter.removeChangeListener(filterListener);
762                                 }
763                             }
764                             scannedBinaries.removeAll (oldBinaries);
765                             final CachingArchiveProvider cap = CachingArchiveProvider.getDefault();
766                             for (URL JavaDoc oldRoot : oldBinaries) {
767                                 cim.removeRoot(oldRoot);
768                                 cap.removeArchive(oldRoot);
769                             }
770                             break;
771                         case COMPILE:
772                         {
773                             try {
774                                 final SingleRootWork sw = (SingleRootWork) work;
775                                 final URL JavaDoc file = sw.getFile();
776                                 final URL JavaDoc root = sw.getRoot ();
777                                 if (sw.isFolder()) {
778                                     handle = ProgressHandleFactory.createHandle(NbBundle.getMessage(RepositoryUpdater.class,"MSG_Updating"));
779                                     handle.start();
780                                     try {
781                                         updateFolder (file, root, false, handle);
782                                     } finally {
783                                         handle.finish();
784                                     }
785                                 }
786                                 else {
787                                     updateFile (file,root);
788                                 }
789                             } catch (Abort abort) {
790                                 //Ignore abort
791
}
792                             break;
793                         }
794                         case DELETE:
795                         {
796                             final SingleRootWork sw = (SingleRootWork) work;
797                             final URL JavaDoc file = sw.getFile();
798                             final URL JavaDoc root = sw.getRoot ();
799                             delete (file, root, sw.isFolder());
800                             break;
801                         }
802                         case UPDATE_BINARY:
803                         {
804                             SingleRootWork sw = (SingleRootWork) work;
805                             final URL JavaDoc file = sw.getFile();
806                             final URL JavaDoc root = sw.getRoot();
807                             updateBinary (file, root);
808                             break;
809                         }
810                     }
811                     return null;
812                 } finally {
813                     if (!continuation) {
814                         synchronized (RepositoryUpdater.this) {
815                             RepositoryUpdater.this.noSubmited--;
816                             if (RepositoryUpdater.this.noSubmited == 0) {
817                                 RepositoryUpdater.this.notifyAll();
818                             }
819                         }
820                         work.finished ();
821                         if (handle != null) {
822                             handle.finish ();
823                         }
824                     }
825                 }
826             }});
827         }
828         
829         private void findDependencies (final URL JavaDoc rootURL, final Stack JavaDoc<URL JavaDoc> cycleDetector, final Map JavaDoc<URL JavaDoc,List JavaDoc<URL JavaDoc>> depGraph,
830             final Set JavaDoc<URL JavaDoc> binaries, final boolean useInitialState) {
831             if (useInitialState && RepositoryUpdater.this.scannedRoots.contains(rootURL)) {
832                 this.oldRoots.remove(rootURL);
833                 return;
834             }
835             if (depGraph.containsKey(rootURL)) {
836                 return;
837             }
838             final FileObject rootFo = URLMapper.findFileObject(rootURL);
839             if (rootFo == null) {
840                 return;
841             }
842             cycleDetector.push (rootURL);
843             final ClassPath bootPath = ClassPath.getClassPath(rootFo, ClassPath.BOOT);
844             final ClassPath compilePath = ClassPath.getClassPath(rootFo, ClassPath.COMPILE);
845             final ClassPath[] pathsToResolve = new ClassPath[] {bootPath,compilePath};
846             final List JavaDoc<URL JavaDoc> deps = new LinkedList JavaDoc<URL JavaDoc> ();
847             for (int i=0; i< pathsToResolve.length; i++) {
848                 final ClassPath pathToResolve = pathsToResolve[i];
849                 if (pathToResolve != null) {
850                     for (ClassPath.Entry entry : pathToResolve.entries()) {
851                         final URL JavaDoc url = entry.getURL();
852                         final URL JavaDoc[] sourceRoots = RepositoryUpdater.this.cpImpl.getSourceRootForBinaryRoot(url, pathToResolve, false);
853                         if (sourceRoots != null) {
854                             for (URL JavaDoc sourceRoot : sourceRoots) {
855                                 if (sourceRoot.equals (rootURL)) {
856                                     this.ignoreExcludes.add (rootURL);
857                                 }
858                                 else if (!cycleDetector.contains(sourceRoot)) {
859                                     deps.add (sourceRoot);
860                                     findDependencies(sourceRoot, cycleDetector,depGraph, binaries, useInitialState);
861                                 }
862                             }
863                         }
864                         else {
865                             if (useInitialState) {
866                                 if (!RepositoryUpdater.this.scannedBinaries.contains(url)) {
867                                     binaries.add (url);
868                                 }
869                                 oldBinaries.remove(url);
870                             }
871                         }
872                     }
873                 }
874             }
875             depGraph.put(rootURL,deps);
876             cycleDetector.pop ();
877         }
878         
879         private boolean scanRoots () {
880             
881             for (Iterator JavaDoc<URL JavaDoc> it = this.newBinaries.iterator(); it.hasNext(); ) {
882                 if (this.canceled.getAndSet(false)) {
883                     return false;
884                 }
885                 final URL JavaDoc rootURL = it.next();
886                 try {
887                     it.remove();
888                     final ClassIndexImpl ci = ClassIndexManager.getDefault().createUsagesQuery(rootURL,false);
889                     RepositoryUpdater.this.scannedBinaries.add (rootURL);
890                     long startT = System.currentTimeMillis();
891                     ci.getBinaryAnalyser().analyse(rootURL, handle);
892                     long endT = System.currentTimeMillis();
893                     if (PERF_TEST) {
894                         try {
895                             Class JavaDoc c = Class.forName("org.netbeans.performance.test.utilities.LoggingScanClasspath",true,Thread.currentThread().getContextClassLoader()); // NOI18N
896
java.lang.reflect.Method JavaDoc m = c.getMethod("reportScanOfFile", new Class JavaDoc[] {String JavaDoc.class, Long JavaDoc.class}); // NOI18N
897
m.invoke(c.newInstance(), new Object JavaDoc[] {rootURL.toExternalForm(), new Long JavaDoc(endT - startT)});
898                         } catch (Exception JavaDoc e) {
899                                 Exceptions.printStackTrace(e);
900                         }
901                     }
902                 } catch (Throwable JavaDoc e) {
903                     if (e instanceof ThreadDeath JavaDoc) {
904                         throw (ThreadDeath JavaDoc) e;
905                     }
906                     else {
907                         Exceptions.attachMessage(e, "While scanning: " + rootURL);
908                         Exceptions.printStackTrace(e);
909                     }
910                 }
911             }
912             for (java.util.ListIterator JavaDoc<URL JavaDoc> it = this.state.listIterator(this.state.size()); it.hasPrevious(); ) {
913                 if (this.canceled.getAndSet(false)) {
914                     return false;
915                 }
916                 try {
917                     final URL JavaDoc rootURL = it.previous();
918                     it.remove();
919                     if (!oldRoots.remove(rootURL) && !RepositoryUpdater.this.scannedRoots.contains(rootURL)) {
920                         long startT = System.currentTimeMillis();
921                         updateFolder (rootURL,rootURL, false, handle);
922                         long endT = System.currentTimeMillis();
923                         if (PERF_TEST) {
924                             try {
925                                 Class JavaDoc c = Class.forName("org.netbeans.performance.test.utilities.LoggingScanClasspath",true,Thread.currentThread().getContextClassLoader()); // NOI18N
926
java.lang.reflect.Method JavaDoc m = c.getMethod("reportScanOfFile", new Class JavaDoc[] {String JavaDoc.class, Long JavaDoc.class}); // NOI18N
927
m.invoke(c.newInstance(), new Object JavaDoc[] {rootURL.toExternalForm(), new Long JavaDoc(endT - startT)});
928                             } catch (Exception JavaDoc e) {
929                                     Exceptions.printStackTrace(e);
930                             }
931                         }
932                     }
933                 } catch (Throwable JavaDoc e) {
934                     if (e instanceof ThreadDeath JavaDoc) {
935                         throw (ThreadDeath JavaDoc) e;
936                     }
937                     else {
938                         Exceptions.printStackTrace (e);
939                     }
940                 }
941             }
942             return true;
943         }
944         
945         private void updateFolder(final URL JavaDoc folder, final URL JavaDoc root, boolean clean, final ProgressHandle handle) throws IOException JavaDoc {
946             final FileObject rootFo = URLMapper.findFileObject(root);
947             if (rootFo == null) {
948                 return;
949             }
950             if (!rootFo.isFolder()) {
951                 LOGGER.warning("Source root has to be a folder: " + FileUtil.getFileDisplayName(rootFo)); // NOI18N
952
return;
953             }
954             final ClassPath sourcePath = ClassPath.getClassPath(rootFo,ClassPath.SOURCE);
955             final ClassPath bootPath = ClassPath.getClassPath(rootFo, ClassPath.BOOT);
956             final ClassPath compilePath = ClassPath.getClassPath(rootFo, ClassPath.COMPILE);
957             final boolean isInitialCompilation = folder.equals(root);
958             if (sourcePath == null || bootPath == null || compilePath == null) {
959                 LOGGER.warning("Ignoring root with no ClassPath: " + FileUtil.getFileDisplayName(rootFo)); // NOI18N
960
return;
961             }
962             try {
963                 final File JavaDoc rootFile = FileUtil.toFile(rootFo);
964                 final File JavaDoc folderFile = isInitialCompilation ? rootFile : FileUtil.normalizeFile(new File JavaDoc (URI.create(folder.toExternalForm())));
965                 if (handle != null) {
966                     final String JavaDoc message = String.format (NbBundle.getMessage(RepositoryUpdater.class,"MSG_Scannig"),rootFile.getAbsolutePath());
967                     handle.setDisplayName(message);
968                 }
969                 //Preprocessor support
970
JavaFileFilterImplementation filter = filters.get(root);
971                 if (filter == null) {
972                     filter = JavaFileFilterQuery.getFilter(rootFo);
973                     if (filter != null) {
974                         if (!filters.values().contains(filter)) {
975                             filter.addChangeListener(filterListener);
976                         }
977                         filters.put(root, filter);
978                     }
979                 }
980                 List JavaDoc<JavaFileObject> toCompile = new LinkedList JavaDoc<JavaFileObject>();
981                 final File JavaDoc classCache = Index.getClassFolder(rootFile);
982                 final Map JavaDoc <String JavaDoc,List JavaDoc<File JavaDoc>> resources = getAllClassFiles(classCache, FileObjects.getRelativePath(rootFile,folderFile),true);
983                 final LazyFileList children = new LazyFileList(folderFile);
984                 ClassIndexImpl uqImpl = ClassIndexManager.getDefault().createUsagesQuery(root, true);
985                 assert uqImpl != null;
986                 SourceAnalyser sa = uqImpl.getSourceAnalyser();
987                 assert sa != null;
988                 boolean invalidIndex = isInitialCompilation && !sa.isValid();
989                 Set JavaDoc<File JavaDoc> rs = new HashSet JavaDoc<File JavaDoc> ();
990                 ClassPath.Entry entry = null;
991                 final ClasspathInfo cpInfo;
992                 if (!this.ignoreExcludes.contains(root)) {
993                     entry = getClassPathEntry(sourcePath, root);
994                     cpInfo = ClasspathInfoAccessor.INSTANCE.create(CacheClassPath.forClassPath(bootPath),CacheClassPath.forClassPath(compilePath),sourcePath,filter,true,false);
995                 }
996                 else {
997                     cpInfo = ClasspathInfoAccessor.INSTANCE.create(CacheClassPath.forClassPath(bootPath),CacheClassPath.forClassPath(compilePath),sourcePath,filter,true,true);
998                 }
999                 for (File JavaDoc child : children) {
1000                    String JavaDoc offset = FileObjects.getRelativePath(rootFile,child);
1001                    if (entry == null || entry.includes(offset.replace(File.separatorChar,'/'))) {
1002                        if (invalidIndex || clean || dirtyCrossFiles.remove(child.toURI())) {
1003                            toCompile.add (FileObjects.fileFileObject(child, rootFile, filter));
1004                        }
1005                        else {
1006                            final int index = offset.lastIndexOf('.'); //NOI18N
1007
if (index > -1) {
1008                                offset = offset.substring(0,index);
1009                            }
1010                            List JavaDoc<File JavaDoc> files = resources.remove(offset);
1011                            if (files==null) {
1012                                toCompile.add(FileObjects.fileFileObject(child, rootFile, filter));
1013                            } else {
1014                                boolean rsf = files.get(0).getName().endsWith(FileObjects.RS);
1015                                if (files.get(0).lastModified() < child.lastModified()) {
1016                                    toCompile.add(FileObjects.fileFileObject(child, rootFile, filter));
1017                                    for (File JavaDoc toDelete : files) {
1018                                        toDelete.delete();
1019                                        if (rsf) {
1020                                            rsf = false;
1021                                        }
1022                                        else {
1023                                            String JavaDoc className = FileObjects.getBinaryName(toDelete,classCache);
1024                                            sa.delete(className);
1025                                        }
1026                                    }
1027                                }
1028                                else if (rsf) {
1029                                    files.remove(0);
1030                                    rs.addAll(files);
1031                                }
1032                            }
1033                        }
1034                    }
1035                }
1036                for (List JavaDoc<File JavaDoc> files : resources.values()) {
1037                    for (File JavaDoc toDelete : files) {
1038                        if (!rs.contains(toDelete)) {
1039                            toDelete.delete();
1040                            if (toDelete.getName().endsWith(FileObjects.SIG)) {
1041                                String JavaDoc className = FileObjects.getBinaryName(toDelete,classCache);
1042                                sa.delete(className);
1043                            }
1044                        }
1045                    }
1046                }
1047                if (!toCompile.isEmpty()) {
1048                    if (handle != null) {
1049                        final String JavaDoc message = String.format (NbBundle.getMessage(RepositoryUpdater.class,"MSG_BackgroundCompile"),rootFile.getAbsolutePath());
1050                        handle.setDisplayName(message);
1051                    }
1052                    batchCompile(toCompile, rootFo, cpInfo, sa, dirtyCrossFiles);
1053                }
1054                sa.store();
1055            } finally {
1056                if (!clean && isInitialCompilation) {
1057                    RepositoryUpdater.this.scannedRoots.add(root);
1058                }
1059            }
1060        }
1061        
1062        private void updateFile (final URL JavaDoc file, final URL JavaDoc root) throws IOException JavaDoc {
1063            final FileObject fo = URLMapper.findFileObject(file);
1064            if (fo == null) {
1065                return;
1066            }
1067            
1068            assert "file".equals(root.getProtocol()) : "Unexpected protocol of URL: " + root; //NOI18N
1069
final ClassIndexImpl uqImpl = ClassIndexManager.getDefault().createUsagesQuery(root, true);
1070            if (uqImpl != null) {
1071                uqImpl.setDirty(null);
1072                final JavaFileFilterImplementation filter = JavaFileFilterQuery.getFilter(fo);
1073                ClasspathInfo cpInfo = ClasspathInfoAccessor.INSTANCE.create (fo, filter, true, false);
1074                final File JavaDoc rootFile = FileUtil.normalizeFile(new File JavaDoc (URI.create(root.toExternalForm())));
1075                final File JavaDoc fileFile = FileUtil.toFile(fo);
1076                final File JavaDoc classCache = Index.getClassFolder (rootFile);
1077                final Map JavaDoc <String JavaDoc,List JavaDoc<File JavaDoc>> resources = getAllClassFiles (classCache, FileObjects.getRelativePath(rootFile, fileFile.getParentFile()),false);
1078                String JavaDoc offset = FileObjects.getRelativePath (rootFile,fileFile);
1079                final int index = offset.lastIndexOf('.'); //NOI18N
1080
if (index > -1) {
1081                    offset = offset.substring(0,index);
1082                }
1083                List JavaDoc<File JavaDoc> files = resources.remove (offset);
1084                SourceAnalyser sa = uqImpl.getSourceAnalyser();
1085                assert sa != null;
1086                if (files != null) {
1087                    for (File JavaDoc toDelete : files) {
1088                        toDelete.delete();
1089                        if (toDelete.getName().endsWith(FileObjects.SIG)) {
1090                            String JavaDoc className = FileObjects.getBinaryName (toDelete,classCache);
1091                            sa.delete (className);
1092                        }
1093                    }
1094                }
1095                else {
1096                    sa.delete(FileObjects.convertFolder2Package(offset, '/')); //NOI18N
1097
}
1098                ClassPath.Entry entry = getClassPathEntry (cpInfo.getClassPath(ClasspathInfo.PathKind.SOURCE),root);
1099                if (entry == null || entry.includes(fo)) {
1100                    String JavaDoc sourceLevel = SourceLevelQuery.getSourceLevel(fo);
1101                    final CompilerListener listener = new CompilerListener ();
1102                    final JavaFileManager fm = ClasspathInfoAccessor.INSTANCE.getFileManager(cpInfo);
1103                    JavaFileObject active = FileObjects.fileFileObject(fileFile, rootFile, filter);
1104                    JavacTaskImpl jt = JavaSourceAccessor.INSTANCE.createJavacTask(cpInfo, listener, sourceLevel);
1105                    jt.setTaskListener(listener);
1106                    Iterable JavaDoc<? extends CompilationUnitTree> trees = jt.parse(new JavaFileObject[] {active});
1107                    jt.enter();
1108                    jt.analyze ();
1109                    dumpClasses(listener.getEnteredTypes(), fm, root.toExternalForm(), null,
1110                        com.sun.tools.javac.code.Types.instance(jt.getContext()),
1111                        com.sun.tools.javac.util.Name.Table.instance(jt.getContext()));
1112                    sa.analyse (trees, jt, fm, active);
1113                    listener.cleanDiagnostics();
1114                    sa.store();
1115                }
1116            }
1117        }
1118        
1119        private void delete (final URL JavaDoc file, final URL JavaDoc root, final boolean folder) throws IOException JavaDoc {
1120            assert "file".equals(root.getProtocol()) : "Unexpected protocol of URL: " + root; //NOI18N
1121
final File JavaDoc rootFile = FileUtil.normalizeFile(new File JavaDoc (URI.create(root.toExternalForm())));
1122            assert "file".equals(file.getProtocol()) : "Unexpected protocol of URL: " + file; //NOI18N
1123
final File JavaDoc fileFile = FileUtil.normalizeFile(new File JavaDoc (URI.create(file.toExternalForm())));
1124            final String JavaDoc offset = FileObjects.getRelativePath (rootFile,fileFile);
1125            assert offset != null && offset.length() > 0 : String.format("File %s not under root %s ", fileFile.getAbsolutePath(), rootFile.getAbsolutePath()); // NOI18N
1126
final File JavaDoc classCache = Index.getClassFolder (rootFile);
1127            File JavaDoc[] affectedFiles = null;
1128            if (folder) {
1129                final File JavaDoc container = new File JavaDoc (classCache, offset);
1130                affectedFiles = container.listFiles();
1131            }
1132            else {
1133                int slashIndex = offset.lastIndexOf (File.separatorChar);
1134                int dotIndex = offset.lastIndexOf('.'); //NOI18N
1135
final File JavaDoc container = slashIndex == -1 ? classCache : new File JavaDoc (classCache,offset.substring(0,slashIndex));
1136                final String JavaDoc name = offset.substring(slashIndex+1, dotIndex);
1137                final String JavaDoc[] patterns = new String JavaDoc[] {
1138                  name + '.',
1139                  name + '$'
1140                };
1141                final File JavaDoc[] content = container.listFiles();
1142                if (content != null) {
1143                    final List JavaDoc<File JavaDoc> result = new ArrayList JavaDoc<File JavaDoc>(content.length);
1144                    for (File JavaDoc f : content) {
1145                        final String JavaDoc fname = f.getName();
1146                        if (fname.startsWith(patterns[0]) || fname.startsWith(patterns[1])) {
1147                            result.add(f);
1148                        }
1149                    }
1150                    affectedFiles = result.toArray(new File JavaDoc[result.size()]);
1151                }
1152            }
1153            if (affectedFiles != null && affectedFiles.length > 0) {
1154                final ClassIndexImpl uqImpl = ClassIndexManager.getDefault().createUsagesQuery(root, true);
1155                assert uqImpl != null;
1156                final SourceAnalyser sa = uqImpl.getSourceAnalyser();
1157                assert sa != null;
1158                for (File JavaDoc f : affectedFiles) {
1159                    if (f.getName().endsWith(FileObjects.RS)) {
1160                        List JavaDoc<File JavaDoc> rsFiles = new LinkedList JavaDoc<File JavaDoc>();
1161                        readRSFile(f, classCache, rsFiles);
1162                        for (File JavaDoc rsf : rsFiles) {
1163                            String JavaDoc className = FileObjects.getBinaryName (rsf,classCache);
1164                            sa.delete (className);
1165                            rsf.delete();
1166                        }
1167                    }
1168                    else {
1169                        String JavaDoc className = FileObjects.getBinaryName (f,classCache);
1170                        sa.delete (className);
1171                    }
1172                    f.delete();
1173                }
1174                sa.store();
1175            }
1176        }
1177        
1178        private void updateBinary (final URL JavaDoc file, final URL JavaDoc root) throws IOException JavaDoc {
1179            CachingArchiveProvider.getDefault().clearArchive(root);
1180            final BinaryAnalyser ba = ClassIndexManager.getDefault().createUsagesQuery(root, false).getBinaryAnalyser();
1181            ba.analyse(root, handle);
1182        }
1183    }
1184    
1185    static class LazyFileList implements Iterable JavaDoc<File JavaDoc> {
1186    
1187        private File JavaDoc root;
1188
1189        public LazyFileList (final File JavaDoc root) {
1190            assert root != null;
1191            this.root = root;
1192        }
1193
1194        public Iterator JavaDoc<File JavaDoc> iterator() {
1195            if (!root.exists()) {
1196                return Collections.<File JavaDoc>emptySet().iterator();
1197            }
1198            return new It (this.root);
1199        }
1200
1201
1202        private class It implements Iterator JavaDoc<File JavaDoc> {
1203
1204            private final List JavaDoc<File JavaDoc> toDo = new LinkedList JavaDoc<File JavaDoc> ();
1205
1206            public It (File JavaDoc root) {
1207                this.toDo.addAll (java.util.Arrays.asList(root.listFiles()));
1208            }
1209
1210            public boolean hasNext() {
1211                while (!toDo.isEmpty()) {
1212                    File JavaDoc f = toDo.remove (0);
1213                    final String JavaDoc name = f.getName();
1214                    if (f.isDirectory() && !ignoredDirectories.contains(name) && Utilities.isJavaIdentifier(name)) {
1215                        File JavaDoc[] content = f.listFiles();
1216                            for (int i=0,j=0;i<content.length;i++) {
1217                                f = content[i];
1218                                if (f.isFile()) {
1219                                    this.toDo.add(j++,f);
1220                                }
1221                                else {
1222                                    this.toDo.add(f);
1223                                }
1224                            }
1225                    }
1226                    else if (name.endsWith('.'+JavaDataLoader.JAVA_EXTENSION) && !PACKAGE_INFO.equals(name) && f.length()>0) { //NOI18N
1227
toDo.add(0,f);
1228                        return true;
1229                    }
1230                }
1231                return false;
1232            }
1233
1234            public File JavaDoc next() {
1235                return toDo.remove (0);
1236            }
1237
1238            public void remove() {
1239                throw new UnsupportedOperationException JavaDoc ();
1240            }
1241
1242        }
1243    }
1244    
1245    
1246    private final class Delay {
1247        
1248        private final Timer JavaDoc timer;
1249        private final List JavaDoc<Work> tasks;
1250        
1251        public Delay () {
1252            this.timer = new Timer JavaDoc ();
1253            this.tasks = new LinkedList JavaDoc<Work> ();
1254        }
1255        
1256        public synchronized void post (final Work work) {
1257            assert work != null;
1258            this.tasks.add (work);
1259            this.timer.schedule(new DelayTask (work),DELAY);
1260        }
1261        
1262        public void cancel () {
1263            Work[] toCancel;
1264            synchronized (this) {
1265                toCancel = this.tasks.toArray (new Work[this.tasks.size()]);
1266            }
1267            for (Work w : toCancel) {
1268                if (w.workType == WorkType.COMPILE) {
1269                    w = new SingleRootWork (WorkType.DELETE,((SingleRootWork)w).file,
1270                        ((SingleRootWork)w).root,((SingleRootWork)w).isFolder,
1271                        w.latch);
1272                }
1273                CompileWorker cw = new CompileWorker (w);
1274                try {
1275                    cw.run (null);
1276                } catch (IOException JavaDoc ioe) {
1277                    Exceptions.printStackTrace(ioe);
1278                }
1279            }
1280        }
1281        
1282        
1283        private class DelayTask extends TimerTask JavaDoc {
1284            
1285            final Work work;
1286            
1287            public DelayTask (final Work work) {
1288                this.work = work;
1289            }
1290            
1291            public void run() {
1292                submit(work);
1293                synchronized (Delay.this) {
1294                    Delay.this.tasks.remove (work);
1295                }
1296            }
1297
1298            public @Override JavaDoc boolean cancel() {
1299                boolean retValue = super.cancel();
1300                if (retValue) {
1301                    synchronized (Delay.this) {
1302                        Delay.this.tasks.remove (work);
1303                    }
1304                }
1305                return retValue;
1306            }
1307        }
1308    }
1309    
1310    private static class CompilerListener implements DiagnosticListener<JavaFileObject>, LowMemoryListener, TaskListener {
1311                               
1312        final List JavaDoc<Diagnostic> errors = new LinkedList JavaDoc<Diagnostic> ();
1313        final List JavaDoc<Diagnostic> warnings = new LinkedList JavaDoc<Diagnostic> ();
1314        final List JavaDoc<ClassSymbol> justEntered = new LinkedList JavaDoc<ClassSymbol> ();
1315        final AtomicBoolean JavaDoc lowMemory = new AtomicBoolean JavaDoc ();
1316        
1317        void cleanDiagnostics () {
1318            if (!this.errors.isEmpty()) {
1319                if (LOGGER.isLoggable(Level.FINE)) {
1320                    for (Diagnostic msg : this.errors) {
1321                        LOGGER.fine(msg.toString()); //NOI18N
1322
}
1323                }
1324                this.errors.clear();
1325            }
1326            if (!this.warnings.isEmpty()) {
1327                if (LOGGER.isLoggable(Level.FINE)) {
1328                    for (Diagnostic msg: this.warnings) {
1329                        LOGGER.fine(msg.toString()); //NOI18N
1330
}
1331                }
1332                this.warnings.clear();
1333            }
1334            this.justEntered.clear();
1335        }
1336        
1337        List JavaDoc<? extends ClassSymbol> getEnteredTypes () {
1338            List JavaDoc<ClassSymbol> result = new ArrayList JavaDoc<ClassSymbol>(this.justEntered);
1339            this.justEntered.clear();
1340            return result;
1341        }
1342        
1343        
1344
1345        public void report(final Diagnostic diagnosticMessage) {
1346            Diagnostic.Kind kind = diagnosticMessage.getKind();
1347            if ( kind == Diagnostic.Kind.ERROR) {
1348                this.errors.add (diagnosticMessage);
1349            }
1350            else if (kind == Diagnostic.Kind.WARNING
1351                   ||kind == Diagnostic.Kind.MANDATORY_WARNING) {
1352                this.warnings.add (diagnosticMessage);
1353            }
1354        }
1355        
1356        public void started(TaskEvent event) {
1357        }
1358        
1359        public void finished(final TaskEvent event) {
1360            if (event.getKind() == TaskEvent.Kind.ENTER) {
1361                final CompilationUnitTree unit = event.getCompilationUnit();
1362                for (Tree typeTree : unit.getTypeDecls()) {
1363                    if (typeTree instanceof JCTree.JCClassDecl) { //May be a JCTree.JCExpressionStatement in case of an error
1364
ClassSymbol sym = ((JCTree.JCClassDecl)typeTree).sym;
1365                        if (sym != null) {
1366                            if (sym.sourcefile == null) {
1367                                sym.sourcefile = event.getSourceFile();
1368                            }
1369                            if (!(sym.sourcefile instanceof FileObjects.ZipFileBase)) {
1370                                this.justEntered.add(sym);
1371                            }
1372                        }
1373                    }
1374                }
1375            }
1376        }
1377        
1378        public void lowMemory (final LowMemoryEvent event) {
1379            this.lowMemory.set(true);
1380        }
1381    }
1382    
1383    public static void batchCompile (final List JavaDoc<JavaFileObject> toCompile, final FileObject rootFo, final ClasspathInfo cpInfo, final SourceAnalyser sa, final Set JavaDoc<URI JavaDoc> dirtyFiles) throws IOException JavaDoc {
1384        assert toCompile != null;
1385        assert rootFo != null;
1386        assert cpInfo != null;
1387        JavaFileObject active = null;
1388        final JavaFileFilterImplementation filter = JavaFileFilterQuery.getFilter(rootFo);
1389        final JavaFileManager fileManager = ClasspathInfoAccessor.INSTANCE.getFileManager(cpInfo);
1390        final CompilerListener listener = new CompilerListener ();
1391        LowMemoryNotifier.getDefault().addLowMemoryListener(listener);
1392        try {
1393            JavacTaskImpl jt = null;
1394            try {
1395                List JavaDoc<JavaFileObject> bigFiles = new LinkedList JavaDoc<JavaFileObject>();
1396                int state = 0;
1397                boolean isBigFile = false;
1398                final String JavaDoc sourceLevel = SourceLevelQuery.getSourceLevel(rootFo);
1399                while (!toCompile.isEmpty() || !bigFiles.isEmpty() || active != null) {
1400                    try {
1401                        if (listener.lowMemory.getAndSet(false)) {
1402                            if (jt != null) {
1403                                jt.finish();
1404                            }
1405                            jt = null;
1406                            if (state == 1) {
1407                                break;
1408                            } else {
1409                                state = 1;
1410                            }
1411                            System.gc();
1412                            continue;
1413                        }
1414                        if (active == null) {
1415                            if (!toCompile.isEmpty()) {
1416                                active = toCompile.remove(0);
1417                                isBigFile = false;
1418                            } else {
1419                                active = bigFiles.remove(0);
1420                                isBigFile = true;
1421                            }
1422                        }
1423                        if (jt == null) {
1424                            jt = JavaSourceAccessor.INSTANCE.createJavacTask(cpInfo, listener, sourceLevel);
1425                            jt.setTaskListener(listener);
1426                            LOGGER.fine("Created new JavacTask for: " + FileUtil.getFileDisplayName(rootFo)); //NOI18N
1427
}
1428                        Iterable JavaDoc<? extends CompilationUnitTree> trees = jt.parse(new JavaFileObject[] {active});
1429                        if (listener.lowMemory.getAndSet(false)) {
1430                            jt.finish();
1431                            jt = null;
1432                            listener.cleanDiagnostics();
1433                            trees = null;
1434                            if (state == 1) {
1435                                if (isBigFile) {
1436                                    break;
1437                                } else {
1438                                    bigFiles.add(active);
1439                                    active = null;
1440                                    state = 0;
1441                                }
1442                            } else {
1443                                state = 1;
1444                            }
1445                            System.gc();
1446                            continue;
1447                        }
1448                        Iterable JavaDoc<? extends TypeElement> types = jt.enterTrees(trees);
1449                        dumpClasses (listener.getEnteredTypes(),fileManager,
1450                                rootFo.getURL().toExternalForm(), dirtyFiles,
1451                                com.sun.tools.javac.code.Types.instance(jt.getContext()),
1452                                com.sun.tools.javac.util.Name.Table.instance(jt.getContext()));
1453                        if (listener.lowMemory.getAndSet(false)) {
1454                            jt.finish();
1455                            jt = null;
1456                            listener.cleanDiagnostics();
1457                            trees = null;
1458                            types = null;
1459                            if (state == 1) {
1460                                if (isBigFile) {
1461                                    break;
1462                                } else {
1463                                    bigFiles.add(active);
1464                                    active = null;
1465                                    state = 0;
1466                                }
1467                            } else {
1468                                state = 1;
1469                            }
1470                            System.gc();
1471                            continue;
1472                        }
1473                        final JavaCompiler jc = JavaCompiler.instance(jt.getContext());
1474                        final JavaFileObject finalActive = active;
1475                        Filter f = new Filter() {
1476                            public void process(Env<AttrContext> env) {
1477                                try {
1478                                    jc.attribute(env);
1479                                } catch (Throwable JavaDoc t) {
1480                                    if (finalActive.toUri().getPath().contains("org/openide/loaders/OpenSupport.java")) {
1481                                        Exceptions.printStackTrace(t);
1482                                    }
1483                                }
1484                            }
1485                        };
1486                        f.run(jc.todo, types);
1487                        dumpClasses (listener.getEnteredTypes(), fileManager,
1488                                rootFo.getURL().toExternalForm(), dirtyFiles,
1489                                com.sun.tools.javac.code.Types.instance(jt.getContext()),
1490                                com.sun.tools.javac.util.Name.Table.instance(jt.getContext()));
1491                        if (listener.lowMemory.getAndSet(false)) {
1492                            jt.finish();
1493                            jt = null;
1494                            listener.cleanDiagnostics();
1495                            trees = null;
1496                            types = null;
1497                            if (state == 1) {
1498                                if (isBigFile) {
1499                                    break;
1500                                } else {
1501                                    bigFiles.add(active);
1502                                    active = null;
1503                                    state = 0;
1504                                }
1505                            } else {
1506                                state = 1;
1507                            }
1508                            System.gc();
1509                            continue;
1510                        }
1511                        if (sa != null) {
1512                            sa.analyse(trees,jt, ClasspathInfoAccessor.INSTANCE.getFileManager(cpInfo), active);
1513                        }
1514                        if (!listener.errors.isEmpty()) {
1515                            Log.instance(jt.getContext()).nerrors = 0;
1516                            listener.cleanDiagnostics();
1517                        }
1518                        active = null;
1519                        state = 0;
1520                    } catch (CouplingAbort a) {
1521                        //coupling error
1522
//TODO: check if the source sig file ~ the source java file:
1523
couplingAbort(a, active);
1524                        if (jt != null) {
1525                            jt.finish();
1526                        }
1527                        jt = null;
1528                        listener.cleanDiagnostics();
1529                        state = 0;
1530                    } catch (Throwable JavaDoc t) {
1531                        if (t instanceof ThreadDeath JavaDoc) {
1532                            throw (ThreadDeath JavaDoc) t;
1533                        }
1534                        else {
1535                            if (jt != null) {
1536                                jt.finish();
1537                            }
1538                            final URI JavaDoc activeURI = active.toUri();
1539                            jt = null;
1540                            active = null;
1541                            listener.cleanDiagnostics();
1542                            if (!(t instanceof Abort)) {
1543                                final ClassPath bootPath = cpInfo.getClassPath(ClasspathInfo.PathKind.BOOT);
1544                                final ClassPath classPath = cpInfo.getClassPath(ClasspathInfo.PathKind.COMPILE);
1545                                final ClassPath sourcePath = cpInfo.getClassPath(ClasspathInfo.PathKind.SOURCE);
1546                                t = Exceptions.attachMessage(t,String.format("Root: %s File: %s Bootpath: %s Classpath: %s Sourcepath: %s",
1547                                        FileUtil.getFileDisplayName(rootFo),
1548                                        activeURI.toString(),
1549                                        bootPath == null ? null : bootPath.toString(),
1550                                        classPath == null ? null : classPath.toString(),
1551                                        sourcePath == null ? null : sourcePath.toString()
1552                                        ));
1553                                Exceptions.printStackTrace(t);
1554                            }
1555                        }
1556                    }
1557                }
1558                if (state == 1) {
1559                    LOGGER.warning("Not enough memory to compile folder: " + FileUtil.getFileDisplayName(rootFo)); // NOI18N
1560
}
1561            } finally {
1562                if (jt != null) {
1563                    jt.finish();
1564                }
1565            }
1566        } finally {
1567            LowMemoryNotifier.getDefault().removeLowMemoryListener(listener);
1568        }
1569    }
1570    
1571    
1572    private static void dumpClasses (final List JavaDoc<? extends ClassSymbol> entered, final JavaFileManager fileManager,
1573        final String JavaDoc currentRoot, final Set JavaDoc<URI JavaDoc> dirtyFiles, final com.sun.tools.javac.code.Types javacTypes,
1574        final com.sun.tools.javac.util.Name.Table nameTable) throws IOException JavaDoc {
1575        for (ClassSymbol classSym : entered) {
1576            JavaFileObject source = classSym.sourcefile;
1577            dumpTopLevel(classSym, fileManager, source, currentRoot, dirtyFiles, javacTypes, nameTable);
1578        }
1579    }
1580    
1581    private static void dumpTopLevel (final ClassSymbol classSym, final JavaFileManager fileManager,
1582        final JavaFileObject source, final String JavaDoc currentRootURL, final Set JavaDoc<URI JavaDoc> dirtyFiles,
1583        final com.sun.tools.javac.code.Types types,
1584        final com.sun.tools.javac.util.Name.Table nameTable) throws IOException JavaDoc {
1585        assert source != null;
1586        if (classSym.getSimpleName() != nameTable.error) {
1587            URI JavaDoc uri = source.toUri();
1588            if (dirtyFiles != null && !uri.toURL().toExternalForm().startsWith(currentRootURL)) {
1589                dirtyFiles.add (uri);
1590            }
1591            final String JavaDoc sourceName = fileManager.inferBinaryName(StandardLocation.SOURCE_PATH, source);
1592            final StringBuilder JavaDoc classNameBuilder = new StringBuilder JavaDoc ();
1593            ClassFileUtil.encodeClassName(classSym, classNameBuilder, '.'); //NOI18N
1594
final String JavaDoc binaryName = classNameBuilder.toString();
1595            Set JavaDoc<String JavaDoc> rsList = null;
1596            if (!sourceName.equals(binaryName)) {
1597                rsList = new HashSet JavaDoc<String JavaDoc>();
1598            }
1599            final JavaFileObject fobj = fileManager.getJavaFileForOutput(StandardLocation.CLASS_OUTPUT, binaryName, JavaFileObject.Kind.CLASS, source);
1600            if ((classSym.asType() instanceof ErrorType) && ((FileObjects.FileBase)fobj).getFile().exists()) {
1601                return;
1602            }
1603            final PrintWriter JavaDoc out = new PrintWriter JavaDoc (new OutputStreamWriter JavaDoc(fobj.openOutputStream()));
1604            try {
1605                SymbolDumper.dump(out,types,classSym,null);
1606            } finally {
1607                out.close();
1608            }
1609            if (rsList != null) {
1610                rsList.add(binaryName);
1611            }
1612            final List JavaDoc<Symbol> enclosedElements = classSym.getEnclosedElements();
1613            for (Symbol ee : enclosedElements) {
1614                if (ee.getKind().isClass() || ee.getKind().isInterface()) {
1615                    dumpClass ((ClassSymbol)ee,fileManager, source, types, nameTable, rsList);
1616                }
1617            }
1618            if (rsList != null) {
1619                final int index = sourceName.lastIndexOf('.'); //NOI18N
1620
final String JavaDoc pkg = index == -1 ? "" : sourceName.substring(0,index); //NOI18N
1621
final String JavaDoc rsName = (index == -1 ? sourceName : sourceName.substring(index+1)) + '.' + FileObjects.RS; //NOI18N
1622
javax.tools.FileObject fo = fileManager.getFileForOutput(StandardLocation.CLASS_OUTPUT, pkg, rsName, source);
1623                assert fo != null;
1624                PrintWriter JavaDoc rsOut = new PrintWriter JavaDoc(fo.openWriter());
1625                try {
1626                    for (String JavaDoc sig : rsList) {
1627                        rsOut.println(sig);
1628                    }
1629                } finally {
1630                    rsOut.close();
1631                }
1632            }
1633        }
1634    }
1635            
1636    private static void dumpClass (final ClassSymbol classSym, final JavaFileManager fileManager, final JavaFileObject source, final com.sun.tools.javac.code.Types types,
1637            final com.sun.tools.javac.util.Name.Table nameTable, final Set JavaDoc<? super String JavaDoc> rsList) throws IOException JavaDoc {
1638        if (classSym.getSimpleName() != nameTable.error) {
1639            final StringBuilder JavaDoc classNameBuilder = new StringBuilder JavaDoc ();
1640            ClassFileUtil.encodeClassName(classSym, classNameBuilder, '.'); //NOI18N
1641
final String JavaDoc binaryName = classNameBuilder.toString();
1642            final JavaFileObject fobj = fileManager.getJavaFileForOutput(StandardLocation.CLASS_OUTPUT, binaryName, JavaFileObject.Kind.CLASS, source);
1643            final PrintWriter JavaDoc out = new PrintWriter JavaDoc (new OutputStreamWriter JavaDoc(fobj.openOutputStream()));
1644            try {
1645                SymbolDumper.dump(out,types,classSym,null);
1646            } finally {
1647                out.close();
1648            }
1649            if (rsList != null) {
1650                rsList.add(binaryName);
1651            }
1652            final List JavaDoc<Symbol> enclosedElements = classSym.getEnclosedElements();
1653            for (Symbol ee : enclosedElements) {
1654                if (ee.getKind().isClass() || ee.getKind().isInterface()) {
1655                    dumpClass ((ClassSymbol)ee,fileManager, source, types, nameTable, rsList);
1656                }
1657            }
1658        }
1659    }
1660    
1661    private static Set JavaDoc<String JavaDoc> parseSet(String JavaDoc propertyName, String JavaDoc defaultValue) {
1662        StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(System.getProperty(propertyName, defaultValue), " \t\n\r\f,-:+!");
1663        Set JavaDoc<String JavaDoc> result = new HashSet JavaDoc<String JavaDoc>();
1664        while (st.hasMoreTokens()) {
1665            result.add(st.nextToken());
1666        }
1667        return result;
1668    }
1669    
1670    
1671    public static Map JavaDoc<String JavaDoc,List JavaDoc<File JavaDoc>> getAllClassFiles (final File JavaDoc root, final String JavaDoc offset, boolean recursive) {
1672        assert root != null;
1673        Map JavaDoc<String JavaDoc,List JavaDoc<File JavaDoc>> result = new HashMap JavaDoc<String JavaDoc,List JavaDoc<File JavaDoc>> ();
1674        String JavaDoc rootName = root.getAbsolutePath();
1675        int len = rootName.length();
1676        if (rootName.charAt(len-1)!=File.separatorChar) {
1677            len++;
1678        }
1679        File JavaDoc folder = root;
1680        if (offset.length() > 0) {
1681            folder = new File JavaDoc (folder,offset); //NOI18N
1682
if (!folder.exists() || !folder.isDirectory()) {
1683                return result;
1684            }
1685        }
1686        getAllClassFilesImpl (folder, root,len,result, recursive);
1687        return result;
1688    }
1689        
1690    private static void getAllClassFilesImpl (final File JavaDoc folder, final File JavaDoc root, final int oi, final Map JavaDoc<String JavaDoc,List JavaDoc<File JavaDoc>> result, final boolean recursive) {
1691        final File JavaDoc[] content = folder.listFiles();
1692        if (content == null) {
1693            LOGGER.info("IO error while listing folder: " + folder.getAbsolutePath() +" isDirectory: " + folder.isDirectory() +" canRead: " + folder.canRead()); //NOI18N
1694
return;
1695        }
1696        for (File JavaDoc f: content) {
1697            if (f.isDirectory() && recursive) {
1698                getAllClassFilesImpl(f, root, oi,result, recursive);
1699            }
1700            else {
1701                String JavaDoc path = f.getAbsolutePath();
1702                int extIndex = path.lastIndexOf('.'); //NO18N
1703
if (extIndex+1+FileObjects.RS.length() == path.length() && path.endsWith(FileObjects.RS)) {
1704                    path = path.substring (oi,extIndex);
1705                    List JavaDoc<File JavaDoc> files = result.get (path);
1706                    if (files == null) {
1707                        files = new LinkedList JavaDoc<File JavaDoc>();
1708                        result.put (path,files);
1709                    }
1710                    files.add(0,f); //the rs file has to be the first
1711
try {
1712                        readRSFile (f,root, files);
1713                    } catch (IOException JavaDoc ioe) {
1714                        //The signature file is broken, report it but don't stop scanning
1715
Exceptions.printStackTrace(ioe);
1716                    }
1717                }
1718                else if (extIndex+1+FileObjects.SIG.length() == path.length() && path.endsWith(FileObjects.SIG)) {
1719                    int index = path.indexOf('$',oi); //NOI18N
1720
if (index == -1) {
1721                        path = path.substring (oi,extIndex);
1722                    }
1723                    else {
1724                        path = path.substring (oi,index);
1725                    }
1726                    List JavaDoc<File JavaDoc> files = result.get (path);
1727                    if (files == null) {
1728                        files = new LinkedList JavaDoc<File JavaDoc>();
1729                        result.put (path,files);
1730                    }
1731                    files.add (f);
1732                }
1733            }
1734        }
1735    }
1736        
1737    private static void readRSFile (final File JavaDoc f, final File JavaDoc root, final List JavaDoc<? super File JavaDoc> files) throws IOException JavaDoc {
1738        BufferedReader JavaDoc in = new BufferedReader JavaDoc (new FileReader JavaDoc (f));
1739        try {
1740            String JavaDoc binaryName;
1741            while ((binaryName=in.readLine())!=null) {
1742                File JavaDoc sf = new File JavaDoc (root, FileObjects.convertPackage2Folder(binaryName)+'.'+FileObjects.SIG);
1743                files.add(sf);
1744            }
1745        } finally {
1746            in.close();
1747        }
1748    }
1749    
1750    
1751    private static ClassPath.Entry getClassPathEntry (final ClassPath cp, final URL JavaDoc root) {
1752        assert cp != null;
1753        assert root != null;
1754        for (ClassPath.Entry e : cp.entries()) {
1755            if (root.equals(e.getURL())) {
1756                return e;
1757            }
1758        }
1759        return null;
1760    }
1761    
1762    
1763    private class FilterListener implements ChangeListener JavaDoc {
1764            
1765        public void stateChanged(ChangeEvent JavaDoc event) {
1766            Object JavaDoc source = event.getSource();
1767            if (source instanceof JavaFileFilterImplementation) {
1768                List JavaDoc<URL JavaDoc> dirtyRoots = new LinkedList JavaDoc<URL JavaDoc> ();
1769                synchronized (filters) {
1770                    for (Map.Entry JavaDoc<URL JavaDoc,JavaFileFilterImplementation> e : filters.entrySet()) {
1771                        if (e.getValue() == source) {
1772                            dirtyRoots.add(e.getKey());
1773                        }
1774                    }
1775                }
1776                submit(Work.filterChange(dirtyRoots));
1777            }
1778        }
1779    }
1780    
1781    public static synchronized RepositoryUpdater getDefault () {
1782        if (instance == null) {
1783            instance = new RepositoryUpdater ();
1784        }
1785        return instance;
1786    }
1787    
1788    private static final int MAX_DUMPS = 255;
1789    
1790    /**
1791     * Dumps the source code to the file. Used for parser debugging. Only a limited number
1792     * of dump files is used. If the last file exists, this method doesn't dump anything.
1793     *
1794     * @param info CompilationInfo for which the error occurred.
1795     * @param exc exception to write to the end of dump file
1796     */

1797    public static void couplingAbort(CouplingAbort a, JavaFileObject source) {
1798        String JavaDoc dumpDir = System.getProperty("netbeans.user") + "/var/log/"; //NOI18N
1799
JavaFileObject classSource = a.getClassFile();
1800        String JavaDoc uri = classSource != null ? classSource.toUri().toASCIIString() : "<unknown>";
1801        String JavaDoc origName = classSource != null ? classSource.getName() : "unknown";
1802        File JavaDoc f = new File JavaDoc(dumpDir + origName + ".dump"); // NOI18N
1803
boolean dumpSucceeded = false;
1804        int i = 1;
1805        while (i < MAX_DUMPS) {
1806            if (!f.exists())
1807                break;
1808            f = new File JavaDoc(dumpDir + origName + '_' + i + ".dump"); // NOI18N
1809
i++;
1810        }
1811        if (!f.exists()) {
1812            try {
1813                OutputStream JavaDoc os = new FileOutputStream JavaDoc(f);
1814                PrintWriter JavaDoc writer = new PrintWriter JavaDoc(new OutputStreamWriter JavaDoc(os, "UTF-8")); // NOI18N
1815
try {
1816                    writer.println(String.format("Coupling error: class file %s, source file %s", uri, source.toUri().toASCIIString()));
1817                    writer.println("----- Sig file content: -------------------------------------------"); // NOI18N
1818
if (classSource == null) {
1819                        writer.println("no content"); //NOI18N
1820
} else {
1821                        if (classSource.getName().toLowerCase().endsWith(".sig")) { // NOI18N
1822
writer.println(classSource.getCharContent(true));
1823                        } else {
1824                            writer.println("not a sig file"); // NOI18N
1825
}
1826                    }
1827                    writer.println("----- Source file content: ----------------------------------------"); // NOI18N
1828
writer.println(source.getCharContent(true));
1829                    writer.println("----- Tree: -------------------------------------------------------"); // NOI18N
1830
writer.println(a.getTree().toString());
1831                    writer.println("----- Coupling Error: ---------------------------------------------"); // NOI18N
1832
a.printStackTrace(writer);
1833                } finally {
1834                    writer.close();
1835                    dumpSucceeded = true;
1836                }
1837            } catch (IOException JavaDoc ioe) {
1838                LOGGER.log(Level.INFO, "Error when writing coupling dump file!", ioe); // NOI18N
1839
}
1840        }
1841        if (dumpSucceeded) {
1842            LOGGER.log(Level.SEVERE, "Coupling error: class file {0}, source file {1}", new Object JavaDoc[] {uri, source.toUri().toASCIIString()});
1843        } else {
1844            LOGGER.log(Level.WARNING,
1845                    "Dump could not be written. Either dump file could not " + // NOI18N
1846
"be created or all dump files were already used. Please " + // NOI18N
1847
"check that you have write permission to '" + dumpDir + "' and " + // NOI18N
1848
"clean all *.dump files in that directory."); // NOI18N
1849
}
1850    }
1851    
1852}
1853
Popular Tags