private void clearCache(IJavaProject project, Set<PackageFragmentRootData> toBeKept) { Collection<PackageFragmentRootData> values; synchronized (cachedPackageFragmentRootData) { values = newArrayList(cachedPackageFragmentRootData.values()); } List<PackageFragmentRootData> toBeRemoved = newArrayList(); for (PackageFragmentRootData data : values) { if (toBeKept.contains(data)) { continue; } // create a copy of the known associated roots to avoid concurrent modification // and conflicts with other readers Map<String, IPackageFragmentRoot> copy = newLinkedHashMap(data.associatedRoots); Iterator<IPackageFragmentRoot> i = copy.values().iterator(); IPackageFragmentRoot someRoot = null; boolean didChange = false; while (i.hasNext()) { IPackageFragmentRoot root = i.next(); if (project.equals(root.getJavaProject())) { i.remove(); didChange = true; } else if (someRoot == null) { someRoot = root; } } if (copy.size() == 0) { toBeRemoved.add(data); } else if (didChange) { // get rid of cached storages that still point to roots / projects that are no longer // available // and recompute them lazily on demand data.associatedRoots = copy; final IPackageFragmentRoot rootToProcess = someRoot; data.uri2Storage = new ForwardingMap<URI, IStorage>() { Map<URI, IStorage> delegate; @Override protected Map<URI, IStorage> delegate() { if (delegate == null) { PackageFragmentRootData newlyCollected = initializeData(rootToProcess); return delegate = newlyCollected.uri2Storage; } return delegate; } }; } } if (!toBeRemoved.isEmpty()) { synchronized (cachedPackageFragmentRootData) { cachedPackageFragmentRootData.values().removeAll(toBeRemoved); } } }
/* @NonNull */ @Override public Iterable<Pair<IStorage, IProject>> getStorages(/* @NonNull */ URI uri) { List<Pair<IStorage, IProject>> result = newArrayListWithCapacity(1); List<PackageFragmentRootData> packageFragmentRootDatas; synchronized (cachedPackageFragmentRootData) { packageFragmentRootDatas = newArrayList(cachedPackageFragmentRootData.values()); } Iterator<PackageFragmentRootData> iterator = packageFragmentRootDatas.iterator(); while (iterator.hasNext()) { PackageFragmentRootData data = iterator.next(); if (data.exists()) { if (data.uriPrefix == null || uri.toString().startsWith(data.uriPrefix.toString())) { IStorage storage = data.uri2Storage.get(uri); if (storage != null) { for (IPackageFragmentRoot root : data.associatedRoots.values()) { result.add(Tuples.create(storage, root.getJavaProject().getProject())); } } } } else { iterator.remove(); } } if (result.isEmpty() && uri.isArchive()) { String authority = uri.authority(); authority = authority.substring(0, authority.length() - 1); URI archiveURI = URI.createURI(authority); if (archiveURI.isFile() || archiveURI.isPlatformResource()) { IPath archivePath = new Path( archiveURI.isPlatformResource() ? archiveURI.toPlatformString(true) : archiveURI.toFileString()); for (PackageFragmentRootData data : packageFragmentRootDatas) { if (data.uriPrefix != null && archivePath.equals(data.getPath())) { // prefixes have an empty last segment. URI prefix = data.uriPrefix.lastSegment().length() == 0 ? data.uriPrefix.trimSegments(1) : data.uriPrefix; URI expectedURI = prefix.appendSegments(uri.segments()); IStorage storage = data.uri2Storage.get(expectedURI); if (storage != null) { for (IPackageFragmentRoot root : data.associatedRoots.values()) { result.add(Tuples.create(storage, root.getJavaProject().getProject())); } } } } } } return result; }
/** @since 2.4 */ protected PackageFragmentRootData initializeData(final IPackageFragmentRoot root) { final PackageFragmentRootData data = new PackageFragmentRootData(computeModificationStamp(root)); data.addRoot(root); try { final SourceAttachmentPackageFragmentRootWalker<Void> walker = new SourceAttachmentPackageFragmentRootWalker<Void>() { @Override protected URI getURI( IFile file, org.eclipse.xtext.ui.resource.PackageFragmentRootWalker.TraversalState state) { if (!uriValidator.isPossiblyManaged(file)) return null; return super.getURI(file, state); } @Override protected URI getURI( IJarEntryResource jarEntry, org.eclipse.xtext.ui.resource.PackageFragmentRootWalker.TraversalState state) { if (!uriValidator.isPossiblyManaged(jarEntry)) return null; final URI uri = locator.getURI(root, jarEntry, state); if (!uriValidator.isValid(uri, jarEntry)) return null; return uri; } @Override protected Void handle( URI uri, IStorage storage, org.eclipse.xtext.ui.resource.PackageFragmentRootWalker.TraversalState state) { data.uri2Storage.put(uri, storage); return null; } }; walker.traverse(root, false); if (walker.getBundleSymbolicName() != null) data.uriPrefix = URI.createPlatformResourceURI(walker.getBundleSymbolicName() + "/", true); } catch (RuntimeException e) { log.error(e.getMessage(), e); } catch (JavaModelException e) { log.debug(e.getMessage(), e); } return data; }
private PackageFragmentRootData getCachedData(IPackageFragmentRoot root) { final String path = root.getPath().toString(); synchronized (cachedPackageFragmentRootData) { if (cachedPackageFragmentRootData.containsKey(path)) { final PackageFragmentRootData data = cachedPackageFragmentRootData.get(path); if (isUpToDate(data, root)) { data.addRoot(root); return data; } else { cachedPackageFragmentRootData.remove(path); } } } PackageFragmentRootData data = initializeData(root); synchronized (cachedPackageFragmentRootData) { cachedPackageFragmentRootData.put(path, data); } return data; }