1 19 package org.netbeans.modules.javacore.classpath; 20 21 22 import java.beans.PropertyChangeListener ; 23 import java.beans.PropertyChangeSupport ; 24 import java.beans.PropertyChangeEvent ; 25 import java.net.URL ; 26 import java.util.*; 27 import org.openide.filesystems.FileObject; 28 import org.openide.filesystems.FileStateInvalidException; 29 import org.netbeans.api.java.classpath.ClassPath; 30 import org.netbeans.api.java.queries.SourceForBinaryQuery; 31 import org.netbeans.modules.javacore.Cache; 32 import org.netbeans.modules.javacore.JMManager; 33 import org.netbeans.spi.java.classpath.ClassPathImplementation; 34 import org.netbeans.spi.java.classpath.ClassPathFactory; 35 import org.netbeans.spi.java.classpath.PathResourceImplementation; 36 import org.netbeans.spi.java.classpath.support.ClassPathSupport; 37 import org.openide.util.WeakListeners; 38 39 40 44 public class FilterClassPathImplementation implements ClassPathImplementation, PropertyChangeListener , Cache.CachedElement { 45 46 private static final boolean DEBUG = false; 47 48 private final PropertyChangeSupport support; 49 private final Object key; 50 private final List resources; 51 private boolean isUpToDate = true; 52 53 private static HashMap resourceCache = new HashMap(); 54 private static HashMap instanceMap = new HashMap(15); 55 private static HashMap implToCP = new HashMap(15); 56 private static Cache cache = new Cache(10); 57 private static ClassPath validator; 58 59 private FilterClassPathImplementation(List original, boolean preferSources) { 60 assert original != null && original.size() > 0 : "Array of original classpaths can not be null or empty or contain nulls: " + original; this.support = new PropertyChangeSupport (this); 62 this.key = getKey(original, preferSources); 63 this.resources = Collections.unmodifiableList(createResources(original, preferSources)); 64 instanceMap.put(key, this); 65 } 66 67 public void release() { 68 if (DEBUG) System.err.println("dropping unused classpath: " + key); implToCP.remove(this); 70 instanceMap.remove(key); 71 } 72 73 public boolean isValid() { 74 return isUpToDate; 75 } 76 77 public void propertyChange(PropertyChangeEvent evt) { 78 isUpToDate = false; 79 } 80 81 public List getResources() { 82 return resources; 83 } 84 85 public void addPropertyChangeListener(PropertyChangeListener listener) { 86 this.support.addPropertyChangeListener (listener); 87 } 88 89 public void removePropertyChangeListener(PropertyChangeListener listener) { 90 this.support.removePropertyChangeListener (listener); 91 } 92 93 private List createResources(List original, boolean preferSources) { 94 List list = new ArrayList (); 95 96 JMManager manager = (JMManager) JMManager.getManager(); 97 98 if (validator == null) { 99 validator = manager.getMergedClassPath(); 100 } 101 Set visited = new HashSet(); 102 Set added = new HashSet(); 103 validator.addPropertyChangeListener((PropertyChangeListener ) WeakListeners.create(PropertyChangeListener .class, this, validator)); 104 if (DEBUG) System.err.println("creating resources from paths: "); for (int j = 0; j < original.size(); j++) { 106 if (DEBUG) System.err.println(" path[" + j + "]"); ClassPath origCP = (ClassPath) original.get(j); 108 if (origCP == null) continue; 109 for (Iterator it = origCP.entries().iterator(); it.hasNext();) { 110 ClassPath.Entry entry = (ClassPath.Entry) it.next(); 111 URL url = entry.getURL(); 112 if (DEBUG) System.err.println(" root: " + url); if (visited.add(url)) { 115 FileObject root = entry.getRoot(); 116 boolean addBinary = false; 117 boolean forceSource = !(root != null && manager.mergedCPContainsRoot(root)); 119 if (DEBUG) System.err.println(" forceSource=" + forceSource); FileObject[] sroots = SourceForBinaryQuery.findSourceRoots (url).getRoots(); 122 if (DEBUG) System.err.println(" source roots: " + Arrays.asList((Object []) sroots)); if (sroots.length > 0) { 127 boolean cont = forceSource; 128 if (!forceSource) { 129 int i = 0; 130 for (; i < sroots.length; i++) { 131 if (!manager.mergedCPContainsRoot(sroots[i])) break; 132 } 133 cont = i >= sroots.length; 134 } 135 if (cont) { 136 for (int i = 0; i < sroots.length; i++) { 137 if (!forceSource || manager.mergedCPContainsRoot(sroots[i])) { 138 try { 139 URL surl = sroots[i].getURL(); 140 if (visited.add(surl)) { 141 if (preferSources || forceSource || sroots.length != 1 || !surl.getProtocol().equals("jar")) { PathResourceImplementation resource = (PathResourceImplementation) resourceCache.get(surl); 145 if (resource == null) { 146 resource = ClassPathSupport.createResource(surl); 147 } 148 resourceCache.put(surl, resource); 149 list.add(resource); 150 added.add(surl); 151 if (DEBUG) System.err.println(" * adding source root: " + surl); } else { 153 addBinary = true; 154 } 155 } else { 156 if (!added.contains(surl)) { 157 addBinary = true; 158 } 159 } 160 } catch (FileStateInvalidException fsie) { 161 } 163 } 164 } 165 } else { 166 addBinary = true; 167 } 168 } else { 169 addBinary = true; 170 } 171 if (addBinary && !forceSource) { 172 PathResourceImplementation resource = (PathResourceImplementation) resourceCache.get(url); 174 if (resource == null) { 175 resource = ClassPathSupport.createResource(url); 176 } 177 resourceCache.put(url, resource); 178 list.add(resource); 179 if (DEBUG) System.err.println(" * adding root: " + url); } 181 } 182 } 183 origCP.addPropertyChangeListener((PropertyChangeListener ) WeakListeners.create(PropertyChangeListener .class, this, origCP)); 184 } 185 return list; 186 } 187 188 private static Object getKey(List original, boolean preferSources) { 189 StringBuffer buf = new StringBuffer (1024); 190 191 ClassPath mergedPath = ((JMManager) JMManager.getManager()).getMergedClassPath(); 192 for (Iterator it = original.iterator(); it.hasNext();) { 193 Object item = it.next(); 194 if (item == mergedPath) { 195 buf.append("Merged"); } else { 197 buf.append(item); 198 } 199 } 200 return buf.toString() + preferSources; 201 } 202 203 public static synchronized ClassPath createClassPath(List original, boolean preferSources) { 204 if (DEBUG) System.err.println("\n**************** request for classpath"); FilterClassPathImplementation instance = (FilterClassPathImplementation) instanceMap.get(getKey(original, preferSources)); 206 ClassPath result; 207 if (instance == null || !instance.isUpToDate) { 208 if (DEBUG) { 209 System.err.println("classpath does not exist or is not up to date - creating..."); Thread.dumpStack(); 211 } 212 instance = new FilterClassPathImplementation(original, preferSources); 213 result = ClassPathFactory.createClassPath(instance); 214 implToCP.put(instance, result); 215 } else { 216 result = (ClassPath) implToCP.get(instance); 217 } 218 cache.put(instance); 219 return result; 220 } 221 } 222 | Popular Tags |