1 19 package org.netbeans.api.java.source; 20 21 import java.beans.PropertyChangeEvent ; 22 import java.beans.PropertyChangeListener ; 23 import java.io.File ; 24 import java.net.URL ; 25 import javax.swing.event.ChangeEvent ; 26 import javax.swing.event.ChangeListener ; 27 import javax.swing.event.EventListenerList ; 28 import javax.tools.JavaFileManager; 29 import org.netbeans.api.java.classpath.ClassPath; 30 import org.netbeans.api.java.platform.JavaPlatformManager; 31 import org.netbeans.api.java.source.ClassIndex; 32 import org.netbeans.modules.java.source.classpath.CacheClassPath; 33 import org.netbeans.modules.java.source.parsing.CachingArchiveProvider; 34 import org.netbeans.modules.java.source.parsing.CachingFileManager; 35 import org.netbeans.modules.java.source.parsing.OutputFileManager; 36 import org.netbeans.modules.java.source.parsing.ProxyFileManager; 37 import org.netbeans.modules.java.source.parsing.SourceFileManager; 38 import org.netbeans.modules.java.preprocessorbridge.spi.JavaFileFilterImplementation; 39 import org.netbeans.modules.java.source.usages.ClasspathInfoAccessor; 40 import org.netbeans.spi.java.classpath.support.ClassPathSupport; 41 import org.openide.ErrorManager; 42 import org.openide.filesystems.FileObject; 43 import org.openide.filesystems.FileUtil; 44 import org.openide.util.WeakListeners; 45 46 50 public final class ClasspathInfo { 51 52 private static final ClassPath EMPTY_PATH = ClassPathSupport.createClassPath(new URL [0]); 53 54 static { 55 ClasspathInfoAccessor.INSTANCE = new ClasspathInfoAccessorImpl (); 56 try { 57 Class.forName(ClassIndex.class.getName(), true, CompilationInfo.class.getClassLoader()); 58 } catch (ClassNotFoundException ex) { 59 ErrorManager.getDefault().notify (ex); 60 } 61 } 62 63 private final CachingArchiveProvider archiveProvider; 64 65 private final ClassPath srcClassPath; 66 private final ClassPath bootClassPath; 67 private final ClassPath compileClassPath; 68 private ClassPath outputClassPath; 69 70 private final ClassPathListener cpListener; 71 private final boolean backgroundCompilation; 72 private final boolean ignoreExcludes; 73 private final JavaFileFilterImplementation filter; 74 private JavaFileManager fileManager; 75 private EventListenerList listenerList = null; 76 private ClassIndex usagesQuery; 77 78 79 private ClasspathInfo(CachingArchiveProvider archiveProvider, ClassPath bootCp, ClassPath compileCp, ClassPath srcCp, 80 JavaFileFilterImplementation filter, boolean backgroundCompilation, boolean ignoreExcludes) { 81 assert archiveProvider != null && bootCp != null && compileCp != null; 82 this.cpListener = new ClassPathListener (); 83 this.archiveProvider = archiveProvider; 84 this.bootClassPath = CacheClassPath.forBootPath(bootCp); 85 this.compileClassPath = CacheClassPath.forClassPath(compileCp); 86 this.bootClassPath.addPropertyChangeListener(WeakListeners.propertyChange(this.cpListener,this.bootClassPath)); 87 this.compileClassPath.addPropertyChangeListener(WeakListeners.propertyChange(this.cpListener,this.compileClassPath)); 88 if ( srcCp != null ) { 89 this.srcClassPath = srcCp; 90 this.outputClassPath = CacheClassPath.forSourcePath (this.srcClassPath); 91 this.srcClassPath.addPropertyChangeListener(WeakListeners.propertyChange(this.cpListener,this.srcClassPath)); 92 } 93 else { 94 this.srcClassPath = ClassPathSupport.createClassPath(new URL [0]); 95 this.outputClassPath = ClassPathSupport.createClassPath(new URL [0]); 96 } 97 this.backgroundCompilation = backgroundCompilation; 98 this.ignoreExcludes = ignoreExcludes; 99 this.filter = filter; 100 } 101 102 public String toString() { 103 return "ClasspathInfo boot:[" + bootClassPath + "],compile:[" + compileClassPath + "],src:[" + srcClassPath + "]"; } 105 106 108 109 114 public static ClasspathInfo create (final File file) { 115 if (file == null) { 116 throw new IllegalArgumentException ("Cannot pass null as parameter of ClasspathInfo.create(java.io.File)"); } 118 final FileObject fo = FileUtil.toFileObject(file); 119 if (fo == null) { 120 return null; 121 } 122 else { 123 return create (fo); 124 } 125 } 126 127 128 private static ClasspathInfo create (FileObject fo, JavaFileFilterImplementation filter, boolean backgroundCompilation, boolean ignoreExcludes) { 129 ClassPath bootPath = ClassPath.getClassPath(fo, ClassPath.BOOT); 130 if (bootPath == null) { 131 bootPath = JavaPlatformManager.getDefault().getDefaultPlatform().getBootstrapLibraries(); 133 } 134 ClassPath compilePath = ClassPath.getClassPath(fo, ClassPath.COMPILE); 135 if (compilePath == null) { 136 compilePath = EMPTY_PATH; 137 } 138 ClassPath srcPath = ClassPath.getClassPath(fo, ClassPath.SOURCE); 139 if (srcPath == null) { 140 srcPath = EMPTY_PATH; 141 } 142 return create (bootPath, compilePath, srcPath, filter, backgroundCompilation, ignoreExcludes); 143 } 144 145 148 public static ClasspathInfo create(FileObject fo) { 149 return create (fo, null, false, false); 150 } 151 152 private static ClasspathInfo create(ClassPath bootPath, ClassPath classPath, ClassPath sourcePath, JavaFileFilterImplementation filter, 153 boolean backgroundCompilation, boolean ignoreExcludes) { 154 return new ClasspathInfo(CachingArchiveProvider.getDefault(), bootPath, classPath, sourcePath, filter, backgroundCompilation, ignoreExcludes); 155 } 156 157 public static ClasspathInfo create(ClassPath bootPath, ClassPath classPath, ClassPath sourcePath) { 158 return new ClasspathInfo(CachingArchiveProvider.getDefault(), bootPath, classPath, sourcePath, null, false, false); 159 } 160 161 163 166 public synchronized void addChangeListener(ChangeListener listener) { 167 if (listenerList == null ) { 168 listenerList = new EventListenerList (); 169 } 170 listenerList.add (ChangeListener .class, listener); 171 } 172 173 176 public synchronized void removeChangeListener(ChangeListener listener) { 177 listenerList.remove (ChangeListener .class, listener); 178 } 179 180 public ClassPath getClassPath (PathKind pathKind) { 181 switch( pathKind ) { 182 case BOOT: 183 return this.bootClassPath; 184 case COMPILE: 185 return this.compileClassPath; 186 case SOURCE: 187 return this.srcClassPath; 188 case OUTPUT: 189 return this.outputClassPath; 190 default: 191 assert false : "Unknown path type"; return null; 193 } 194 } 195 196 197 public synchronized ClassIndex getClassIndex () { 198 if ( usagesQuery == null ) { 199 usagesQuery = new ClassIndex ( 200 this.bootClassPath, 201 this.compileClassPath, 202 this.srcClassPath); 203 } 204 return usagesQuery; 205 } 206 207 209 synchronized JavaFileManager getFileManager() { 210 if (this.fileManager == null) { 211 boolean hasSources = this.srcClassPath != null; 212 this.fileManager = new ProxyFileManager ( 213 new CachingFileManager (this.archiveProvider, this.bootClassPath, true, true), 214 new CachingFileManager (this.archiveProvider, this.compileClassPath, false, true), 215 hasSources ? (backgroundCompilation ? new CachingFileManager (this.archiveProvider, this.srcClassPath, filter, false, ignoreExcludes) 216 : new SourceFileManager (this.srcClassPath, ignoreExcludes)) : null, 217 hasSources ? new OutputFileManager (this.archiveProvider, this.outputClassPath, this.srcClassPath) : null 218 ); 219 } 220 return this.fileManager; 221 } 222 223 225 private void fireChangeListenerStateChanged() { 226 ChangeEvent e = null; 227 if (listenerList == null) return; 228 Object [] listeners = listenerList.getListenerList (); 229 for (int i = listeners.length - 2; i >= 0; i -= 2) { 230 if (listeners[i]==ChangeListener .class) { 231 if (e == null) 232 e = new ChangeEvent (this); 233 ((ChangeListener )listeners[i+1]).stateChanged (e); 234 } 235 } 236 } 237 238 239 241 public static enum PathKind { 242 BOOT, 243 COMPILE, 244 SOURCE, 245 OUTPUT, 246 247 } 248 249 private class ClassPathListener implements PropertyChangeListener { 250 251 public void propertyChange (PropertyChangeEvent event) { 252 if (ClassPath.PROP_ROOTS.equals(event.getPropertyName())) { 253 synchronized (this) { 254 fileManager = null; 256 usagesQuery = null; 258 } 259 fireChangeListenerStateChanged(); 260 } 261 } 262 } 263 264 private static class ClasspathInfoAccessorImpl extends ClasspathInfoAccessor { 265 266 @Override 267 public JavaFileManager getFileManager(ClasspathInfo cpInfo) { 268 return cpInfo.getFileManager(); 269 } 270 271 @Override 272 public ClasspathInfo create (ClassPath bootPath, ClassPath classPath, ClassPath sourcePath, JavaFileFilterImplementation filter, boolean backgroundCompilation, boolean ignoreExcludes) { 273 return ClasspathInfo.create(bootPath, classPath, sourcePath, filter, backgroundCompilation, ignoreExcludes); 274 } 275 276 @Override 277 public ClasspathInfo create (FileObject fo, JavaFileFilterImplementation filter, boolean backgroundCompilation, boolean ignoreExcludes) { 278 return ClasspathInfo.create(fo, filter, backgroundCompilation, ignoreExcludes); 279 } 280 } 281 } 282 | Popular Tags |