1 13 package org.eclipse.core.internal.resources; 14 15 import java.net.URI ; 16 import java.util.*; 17 import org.eclipse.core.filesystem.EFS; 18 import org.eclipse.core.filesystem.IFileStore; 19 import org.eclipse.core.internal.events.ILifecycleListener; 20 import org.eclipse.core.internal.events.LifecycleEvent; 21 import org.eclipse.core.internal.localstore.FileSystemResourceManager; 22 import org.eclipse.core.internal.utils.Messages; 23 import org.eclipse.core.resources.*; 24 import org.eclipse.core.runtime.*; 25 import org.eclipse.osgi.util.NLS; 26 27 50 public class AliasManager implements IManager, ILifecycleListener, IResourceChangeListener { 51 public class AddToCollectionDoit implements Doit { 52 Collection collection; 53 54 public void doit(IResource resource) { 55 collection.add(resource); 56 } 57 58 public void setCollection(Collection collection) { 59 this.collection = collection; 60 } 61 } 62 63 interface Doit { 64 public void doit(IResource resource); 65 } 66 67 class FindAliasesDoit implements Doit { 68 private int aliasType; 69 private IPath searchPath; 70 71 public void doit(IResource match) { 72 if (match.getFullPath().isPrefixOf(searchPath)) 74 return; 75 IPath aliasPath = null; 76 switch (match.getType()) { 77 case IResource.PROJECT : 78 if (suffix.segmentCount() > 0) { 80 IResource testResource = ((IProject) match).findMember(suffix.segment(0)); 81 if (testResource != null && testResource.isLinked()) 82 return; 83 } 84 aliasPath = match.getFullPath().append(suffix); 86 break; 87 case IResource.FOLDER : 88 aliasPath = match.getFullPath().append(suffix); 89 break; 90 case IResource.FILE : 91 if (suffix.segmentCount() == 0) 92 aliasPath = match.getFullPath(); 93 break; 94 } 95 if (aliasPath != null) 96 if (aliasType == IResource.FILE) { 97 aliases.add(workspace.getRoot().getFile(aliasPath)); 98 } else { 99 if (aliasPath.segmentCount() == 1) 100 aliases.add(workspace.getRoot().getProject(aliasPath.lastSegment())); 101 else 102 aliases.add(workspace.getRoot().getFolder(aliasPath)); 103 } 104 } 105 106 109 public void setSearchAlias(IResource aliasResource) { 110 this.aliasType = aliasResource.getType(); 111 this.searchPath = aliasResource.getFullPath(); 112 } 113 } 114 115 119 class LocationMap { 120 123 private final SortedMap map = new TreeMap(getComparator()); 124 125 129 public boolean add(IFileStore location, IResource resource) { 130 Object oldValue = map.get(location); 131 if (oldValue == null) { 132 map.put(location, resource); 133 return true; 134 } 135 if (oldValue instanceof IResource) { 136 if (resource.equals(oldValue)) 137 return false; ArrayList newValue = new ArrayList(2); 139 newValue.add(oldValue); 140 newValue.add(resource); 141 map.put(location, newValue); 142 return true; 143 } 144 ArrayList list = (ArrayList) oldValue; 145 if (list.contains(resource)) 146 return false; list.add(resource); 148 return true; 149 } 150 151 154 public void clear() { 155 map.clear(); 156 } 157 158 162 public void matchingPrefixDo(IFileStore prefix, Doit doit) { 163 SortedMap matching; 164 IFileStore prefixParent = prefix.getParent(); 165 if (prefixParent != null) { 166 IFileStore endPoint = prefixParent.getChild(prefix.getName() + "\0"); matching = map.subMap(prefix, endPoint); 170 } else { 171 matching = map; 172 } 173 for (Iterator it = matching.values().iterator(); it.hasNext();) { 174 Object value = it.next(); 175 if (value == null) 176 return; 177 if (value instanceof List) { 178 Iterator duplicates = ((List) value).iterator(); 179 while (duplicates.hasNext()) 180 doit.doit((IResource) duplicates.next()); 181 } else { 182 doit.doit((IResource) value); 183 } 184 } 185 } 186 187 191 public void matchingResourcesDo(IFileStore location, Doit doit) { 192 Object value = map.get(location); 193 if (value == null) 194 return; 195 if (value instanceof List) { 196 Iterator duplicates = ((List) value).iterator(); 197 while (duplicates.hasNext()) 198 doit.doit((IResource) duplicates.next()); 199 } else { 200 doit.doit((IResource) value); 201 } 202 } 203 204 208 public void overLappingResourcesDo(Doit doit) { 209 Iterator entries = map.entrySet().iterator(); 210 IFileStore previousStore = null; 211 IResource previousResource = null; 212 while (entries.hasNext()) { 213 Map.Entry current = (Map.Entry) entries.next(); 214 IFileStore currentStore = (IFileStore) current.getKey(); 216 IResource currentResource = null; 217 Object value = current.getValue(); 218 if (value instanceof List) { 219 Iterator duplicates = ((List) value).iterator(); 221 while (duplicates.hasNext()) 222 doit.doit(((IResource) duplicates.next()).getProject()); 223 } else { 224 currentResource = (IResource) value; 226 } 227 if (previousStore != null) { 228 if (previousStore.isParentOf(currentStore)) { 231 if (previousResource != null) { 234 doit.doit(previousResource.getProject()); 235 previousResource = null; 237 } 238 if (currentResource != null) 239 doit.doit(currentResource.getProject()); 240 continue; 242 } 243 } 244 previousStore = currentStore; 245 previousResource = currentResource; 246 } 247 } 248 249 253 public boolean remove(IFileStore location, IResource resource) { 254 Object oldValue = map.get(location); 255 if (oldValue == null) 256 return false; 257 if (oldValue instanceof IResource) { 258 if (resource.equals(oldValue)) { 259 map.remove(location); 260 return true; 261 } 262 return false; 263 } 264 ArrayList list = (ArrayList) oldValue; 265 boolean wasRemoved = list.remove(resource); 266 if (list.size() == 0) 267 map.remove(location); 268 return wasRemoved; 269 } 270 } 271 272 275 private final AddToCollectionDoit addToCollection = new AddToCollectionDoit(); 276 277 280 protected final Set aliasedProjects = new HashSet(); 281 282 286 protected final HashSet aliases = new HashSet(); 287 288 293 private final Set changedLinks = new HashSet(); 294 295 299 private boolean changedProjects = false; 300 301 304 private final FindAliasesDoit findAliases = new FindAliasesDoit(); 305 306 310 protected final LocationMap locationsMap = new LocationMap(); 311 319 private int nonDefaultResourceCount = 0; 320 321 327 public IPath suffix; 328 329 330 protected final Workspace workspace; 331 332 public AliasManager(Workspace workspace) { 333 this.workspace = workspace; 334 } 335 336 private void addToLocationsMap(IProject project) { 337 IFileStore location = ((Resource) project).getStore(); 338 if (location != null) 339 locationsMap.add(location, project); 340 ProjectDescription description = ((Project) project).internalGetDescription(); 341 if (description == null) 342 return; 343 if (description.getLocationURI() != null) 344 nonDefaultResourceCount++; 345 HashMap links = description.getLinks(); 346 if (links == null) 347 return; 348 for (Iterator it = links.values().iterator(); it.hasNext();) { 349 LinkDescription linkDesc = (LinkDescription) it.next(); 350 IResource link = project.findMember(linkDesc.getProjectRelativePath()); 351 if (link != null) { 352 try { 353 addToLocationsMap(link, EFS.getStore(linkDesc.getLocationURI())); 354 } catch (CoreException e) { 355 } 357 } 358 } 359 } 360 361 private void addToLocationsMap(IResource link, IFileStore location) { 362 if (location != null) 363 if (locationsMap.add(location, link)) 364 nonDefaultResourceCount++; 365 } 366 367 370 private void buildAliasedProjectsSet() { 371 aliasedProjects.clear(); 372 if (nonDefaultResourceCount <= 0) 374 return; 375 addToCollection.setCollection(aliasedProjects); 377 locationsMap.overLappingResourcesDo(addToCollection); 378 } 379 380 384 private void buildLocationsMap() { 385 locationsMap.clear(); 386 nonDefaultResourceCount = 0; 387 IProject[] projects = workspace.getRoot().getProjects(); 389 for (int i = 0; i < projects.length; i++) 390 if (projects[i].isAccessible()) 391 addToLocationsMap(projects[i]); 392 } 393 394 404 private boolean checkDeletion(Project project, IFileStore location) throws CoreException { 405 if (project.exists() && !location.fetchInfo().exists()) { 406 Assert.isTrue(workspace.getWorkManager().getLock().getDepth() > 0); 411 project.deleteResource(false, null); 412 return true; 413 } 414 return false; 415 } 416 417 420 public IResource[] computeAliases(final IResource resource, IFileStore location) { 421 if (hasNoAliases(resource)) 423 return null; 424 425 aliases.clear(); 426 internalComputeAliases(resource, location); 427 int size = aliases.size(); 428 if (size == 0) 429 return null; 430 return (IResource[]) aliases.toArray(new IResource[size]); 431 } 432 433 437 private void computeDeepAliases(IResource resource, IFileStore location) { 438 if (location == null) 440 return; 441 internalComputeAliases(resource, location); 443 addToCollection.setCollection(aliases); 445 locationsMap.matchingPrefixDo(location, addToCollection); 446 if (resource.getType() == IResource.PROJECT) { 448 try { 449 IResource[] members = ((IProject) resource).members(); 450 final FileSystemResourceManager localManager = workspace.getFileSystemManager(); 451 for (int i = 0; i < members.length; i++) { 452 if (members[i].isLinked()) { 453 IFileStore linkLocation = localManager.getStore(members[i]); 454 if (linkLocation != null) 455 locationsMap.matchingPrefixDo(linkLocation, addToCollection); 456 } 457 } 458 } catch (CoreException e) { 459 } 461 } 462 } 463 464 471 private Comparator getComparator() { 472 return new Comparator() { 473 public int compare(Object o1, Object o2) { 474 IFileStore store1 = (IFileStore) o1; 475 IFileStore store2 = (IFileStore) o2; 476 int compare = compareStringOrNull(store1.getFileSystem().getScheme(), store2.getFileSystem().getScheme()); 478 if (compare != 0) 479 return compare; 480 final URI uri1 = store1.toURI(); 482 final URI uri2 = store2.toURI(); 483 IPath path1 = new Path(uri1.getPath()); 484 IPath path2 = new Path(uri2.getPath()); 485 int segmentCount1 = path1.segmentCount(); 486 int segmentCount2 = path2.segmentCount(); 487 for (int i = 0; (i < segmentCount1) && (i < segmentCount2); i++) { 488 compare = path1.segment(i).compareTo(path2.segment(i)); 489 if (compare != 0) 490 return compare; 491 } 492 compare = segmentCount1 - segmentCount2; 494 if (compare != 0) 495 return compare; 496 return compareStringOrNull(uri1.getQuery(), uri2.getQuery()); 498 } 499 500 503 private int compareStringOrNull(String string1, String string2) { 504 if (string1 == null) { 505 if (string2 == null) 506 return 0; 507 return 1; 508 } 509 if (string2 == null) 510 return -1; 511 return string1.compareTo(string2); 512 513 } 514 }; 515 } 516 517 public void handleEvent(LifecycleEvent event) { 518 524 switch (event.kind) { 525 case LifecycleEvent.PRE_LINK_DELETE : 526 Resource link = (Resource) event.resource; 527 if (link.isLinked()) 528 removeFromLocationsMap(link, link.getStore()); 529 case LifecycleEvent.PRE_LINK_CREATE : 531 changedLinks.add(event.resource); 532 break; 533 case LifecycleEvent.PRE_LINK_COPY : 534 changedLinks.add(event.newResource); 535 break; 536 case LifecycleEvent.PRE_LINK_MOVE : 537 link = (Resource) event.resource; 538 if (link.isLinked()) 539 removeFromLocationsMap(link, link.getStore()); 540 changedLinks.add(event.newResource); 541 break; 542 } 543 } 544 545 549 private boolean hasNoAliases(final IResource resource) { 550 IProject project = resource.getProject(); 553 boolean noAliases = !aliasedProjects.contains(project); 554 555 if (hasStructureChanges()) { 557 updateStructureChanges(); 558 noAliases &= nonDefaultResourceCount <= 0 || !aliasedProjects.contains(project); 559 } 560 return noAliases; 561 } 562 563 566 private boolean hasStructureChanges() { 567 return changedProjects || !changedLinks.isEmpty(); 568 } 569 570 574 private void internalComputeAliases(IResource resource, IFileStore location) { 575 IFileStore searchLocation = location; 576 if (searchLocation == null) 577 searchLocation = ((Resource) resource).getStore(); 578 if (searchLocation == null) 580 return; 581 582 suffix = Path.EMPTY; 583 findAliases.setSearchAlias(resource); 584 589 do { 590 locationsMap.matchingResourcesDo(searchLocation, findAliases); 591 suffix = new Path(searchLocation.getName()).append(suffix); 592 searchLocation = searchLocation.getParent(); 593 } while (searchLocation != null); 594 } 595 596 private void removeFromLocationsMap(IResource link, IFileStore location) { 597 if (location != null) 598 if (locationsMap.remove(location, link)) 599 nonDefaultResourceCount--; 600 } 601 602 public void resourceChanged(IResourceChangeEvent event) { 603 final IResourceDelta delta = event.getDelta(); 604 if (delta == null) 605 return; 606 if (delta.getAffectedChildren(IResourceDelta.ADDED | IResourceDelta.REMOVED).length > 0) 608 changedProjects = true; 609 } 610 611 614 public void shutdown(IProgressMonitor monitor) { 615 workspace.removeResourceChangeListener(this); 616 locationsMap.clear(); 617 } 618 619 622 public void startup(IProgressMonitor monitor) { 623 workspace.addLifecycleListener(this); 624 workspace.addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE); 625 buildLocationsMap(); 626 buildAliasedProjectsSet(); 627 } 628 629 641 public void updateAliases(IResource resource, IFileStore location, int depth, IProgressMonitor monitor) throws CoreException { 642 if (hasNoAliases(resource)) 643 return; 644 aliases.clear(); 645 if (depth == IResource.DEPTH_ZERO) 646 internalComputeAliases(resource, location); 647 else 648 computeDeepAliases(resource, location); 649 if (aliases.size() == 0) 650 return; 651 FileSystemResourceManager localManager = workspace.getFileSystemManager(); 652 for (Iterator it = aliases.iterator(); it.hasNext();) { 653 IResource alias = (IResource) it.next(); 654 monitor.subTask(NLS.bind(Messages.links_updatingDuplicate, alias.getFullPath())); 655 if (alias.getType() == IResource.PROJECT) { 656 if (checkDeletion((Project) alias, location)) 657 continue; 658 } 660 localManager.refresh(alias, IResource.DEPTH_INFINITE, false, null); 661 } 662 } 663 664 668 private void updateStructureChanges() { 669 boolean hadChanges = false; 670 if (changedProjects) { 671 changedProjects = false; 673 hadChanges = true; 674 buildLocationsMap(); 675 } else { 676 for (Iterator it = changedLinks.iterator(); it.hasNext();) { 678 IResource resource = (IResource) it.next(); 679 hadChanges = true; 680 if (!resource.isAccessible()) 681 continue; 682 if (resource.isLinked()) 683 addToLocationsMap(resource, ((Resource) resource).getStore()); 684 } 685 } 686 changedLinks.clear(); 687 if (hadChanges) 688 buildAliasedProjectsSet(); 689 changedProjects = false; 690 } 691 } 692 | Popular Tags |