1 11 package org.eclipse.core.internal.resources; 12 13 import java.io.*; 14 import java.util.*; 15 import org.eclipse.core.internal.localstore.SafeChunkyInputStream; 16 import org.eclipse.core.internal.localstore.SafeFileInputStream; 17 import org.eclipse.core.internal.utils.Messages; 18 import org.eclipse.core.internal.utils.Policy; 19 import org.eclipse.core.internal.watson.*; 20 import org.eclipse.core.resources.*; 21 import org.eclipse.core.runtime.*; 22 import org.eclipse.osgi.util.NLS; 23 24 27 public class MarkerManager implements IManager { 28 29 private static final MarkerInfo[] NO_MARKER_INFO = new MarkerInfo[0]; 31 private static final IMarker[] NO_MARKERS = new IMarker[0]; 32 protected MarkerTypeDefinitionCache cache = new MarkerTypeDefinitionCache(); 33 private long changeId = 0; 34 protected Map currentDeltas = null; 35 protected final MarkerDeltaManager deltaManager = new MarkerDeltaManager(); 36 37 protected Workspace workspace; 38 protected MarkerWriter writer = new MarkerWriter(this); 39 40 43 public MarkerManager(Workspace workspace) { 44 this.workspace = workspace; 45 } 46 47 52 public void add(IResource resource, MarkerInfo newMarker) throws CoreException { 53 Resource target = (Resource) resource; 54 ResourceInfo info = workspace.getResourceInfo(target.getFullPath(), false, false); 55 target.checkExists(target.getFlags(info), false); 56 info = workspace.getResourceInfo(resource.getFullPath(), false, true); 57 if (info == null) 59 return; 60 if (isPersistent(newMarker)) 63 info.set(ICoreConstants.M_MARKERS_SNAP_DIRTY); 64 MarkerSet markers = info.getMarkers(true); 66 if (markers == null) 67 markers = new MarkerSet(1); 68 basicAdd(resource, markers, newMarker); 69 if (!markers.isEmpty()) 70 info.setMarkers(markers); 71 } 72 73 78 private void basicAdd(IResource resource, MarkerSet markers, MarkerInfo newMarker) throws CoreException { 79 if (newMarker.getId() != MarkerInfo.UNDEFINED_ID) { 81 String message = Messages.resources_changeInAdd; 82 throw new ResourceException(new ResourceStatus(IResourceStatus.INTERNAL_ERROR, resource.getFullPath(), message)); 83 } 84 newMarker.setId(workspace.nextMarkerId()); 85 markers.add(newMarker); 86 IMarkerSetElement[] changes = new IMarkerSetElement[1]; 87 changes[0] = new MarkerDelta(IResourceDelta.ADDED, resource, newMarker); 88 changedMarkers(resource, changes); 89 } 90 91 94 protected MarkerInfo[] basicFindMatching(MarkerSet markers, String type, boolean includeSubtypes) { 95 int size = markers.size(); 96 if (size <= 0) 97 return NO_MARKER_INFO; 98 List result = new ArrayList(size); 99 IMarkerSetElement[] elements = markers.elements(); 100 for (int i = 0; i < elements.length; i++) { 101 MarkerInfo marker = (MarkerInfo) elements[i]; 102 if (type == null) 104 result.add(marker); 105 else { 106 if (includeSubtypes) { 107 if (cache.isSubtype(marker.getType(), type)) 108 result.add(marker); 109 } else { 110 if (marker.getType().equals(type)) 111 result.add(marker); 112 } 113 } 114 } 115 size = result.size(); 116 if (size <= 0) 117 return NO_MARKER_INFO; 118 return (MarkerInfo[]) result.toArray(new MarkerInfo[size]); 119 } 120 121 protected int basicFindMaxSeverity(MarkerSet markers, String type, boolean includeSubtypes) { 122 int max = -1; 123 int size = markers.size(); 124 if (size <= 0) 125 return max; 126 IMarkerSetElement[] elements = markers.elements(); 127 for (int i = 0; i < elements.length; i++) { 128 MarkerInfo marker = (MarkerInfo) elements[i]; 129 if (type == null) 131 max = Math.max(max, getSeverity(marker)); 132 else { 133 if (includeSubtypes) { 134 if (cache.isSubtype(marker.getType(), type)) 135 max = Math.max(max, getSeverity(marker)); 136 } else { 137 if (marker.getType().equals(type)) 138 max = Math.max(max, getSeverity(marker)); 139 } 140 } 141 if (max >= IMarker.SEVERITY_ERROR) { 142 break; 143 } 144 } 145 return max; 146 } 147 148 private int getSeverity(MarkerInfo marker) { 149 Object o = marker.getAttribute(IMarker.SEVERITY); 150 if (o instanceof Integer ) { 151 Integer i = (Integer ) o; 152 return i.intValue(); 153 } 154 return -1; 155 } 156 157 162 protected void basicRemoveMarkers(ResourceInfo info, IPathRequestor requestor, String type, boolean includeSubtypes) { 163 MarkerSet markers = info.getMarkers(false); 164 if (markers == null) 165 return; 166 IMarkerSetElement[] matching; 167 IPath path; 168 if (type == null) { 169 path = requestor.requestPath(); 172 info = workspace.getResourceInfo(path, false, true); 173 info.setMarkers(null); 174 matching = markers.elements(); 175 } else { 176 matching = basicFindMatching(markers, type, includeSubtypes); 177 if (matching.length == 0) 179 return; 180 path = requestor.requestPath(); 182 info = workspace.getResourceInfo(path, false, true); 183 markers = info.getMarkers(true); 185 markers.removeAll(matching); 188 info.setMarkers(markers.size() == 0 ? null : markers); 189 } 190 info.set(ICoreConstants.M_MARKERS_SNAP_DIRTY); 191 IMarkerSetElement[] changes = new IMarkerSetElement[matching.length]; 192 IResource resource = workspace.getRoot().findMember(path); 193 for (int i = 0; i < matching.length; i++) 194 changes[i] = new MarkerDelta(IResourceDelta.REMOVED, resource, (MarkerInfo) matching[i]); 195 changedMarkers(resource, changes); 196 return; 197 } 198 199 202 protected void buildMarkers(IMarkerSetElement[] markers, IPath path, int type, ArrayList list) { 203 if (markers.length == 0) 204 return; 205 IResource resource = workspace.newResource(path, type); 206 list.ensureCapacity(list.size() + markers.length); 207 for (int i = 0; i < markers.length; i++) { 208 list.add(new Marker(resource, ((MarkerInfo) markers[i]).getId())); 209 } 210 } 211 212 215 protected void changedMarkers(IResource resource, IMarkerSetElement[] changes) { 216 if (changes == null || changes.length == 0) 217 return; 218 changeId++; 219 if (currentDeltas == null) 220 currentDeltas = deltaManager.newGeneration(changeId); 221 IPath path = resource.getFullPath(); 222 MarkerSet previousChanges = (MarkerSet) currentDeltas.get(path); 223 MarkerSet result = MarkerDelta.merge(previousChanges, changes); 224 if (result.size() == 0) 225 currentDeltas.remove(path); 226 else 227 currentDeltas.put(path, result); 228 ResourceInfo info = workspace.getResourceInfo(path, false, true); 229 if (info != null) 230 info.incrementMarkerGenerationCount(); 231 } 232 233 236 public IMarker findMarker(IResource resource, long id) { 237 MarkerInfo info = findMarkerInfo(resource, id); 238 return info == null ? null : new Marker(resource, info.getId()); 239 } 240 241 244 public MarkerInfo findMarkerInfo(IResource resource, long id) { 245 ResourceInfo info = workspace.getResourceInfo(resource.getFullPath(), false, false); 246 if (info == null) 247 return null; 248 MarkerSet markers = info.getMarkers(false); 249 if (markers == null) 250 return null; 251 return (MarkerInfo) markers.get(id); 252 } 253 254 260 public IMarker[] findMarkers(IResource target, final String type, final boolean includeSubtypes, int depth) { 261 ArrayList result = new ArrayList(); 262 doFindMarkers(target, result, type, includeSubtypes, depth); 263 if (result.size() == 0) 264 return NO_MARKERS; 265 return (IMarker[]) result.toArray(new IMarker[result.size()]); 266 } 267 268 274 public void doFindMarkers(IResource target, ArrayList result, final String type, final boolean includeSubtypes, int depth) { 275 if (depth == IResource.DEPTH_INFINITE && target.getType() != IResource.FILE) 277 visitorFindMarkers(target.getFullPath(), result, type, includeSubtypes); 278 else 279 recursiveFindMarkers(target.getFullPath(), result, type, includeSubtypes, depth); 280 } 281 282 286 public int findMaxProblemSeverity(IResource target, String type, boolean includeSubtypes, int depth) { 287 if (depth == IResource.DEPTH_INFINITE && target.getType() != IResource.FILE) 289 return visitorFindMaxSeverity(target.getFullPath(), type, includeSubtypes); 290 return recursiveFindMaxSeverity(target.getFullPath(), type, includeSubtypes, depth); 291 } 292 293 public long getChangeId() { 294 return changeId; 295 } 296 297 300 public Map getMarkerDeltas(long startChangeId) { 301 return deltaManager.assembleDeltas(startChangeId); 302 } 303 304 308 boolean hasDelta(IPath path, long id) { 309 if (currentDeltas == null) 310 return false; 311 MarkerSet set = (MarkerSet) currentDeltas.get(path); 312 if (set == null) 313 return false; 314 return set.get(id) != null; 315 } 316 317 321 public boolean isPersistent(MarkerInfo info) { 322 if (!cache.isPersistent(info.getType())) 323 return false; 324 Object isTransient = info.getAttribute(IMarker.TRANSIENT); 325 return isTransient == null || !(isTransient instanceof Boolean ) || !((Boolean ) isTransient).booleanValue(); 326 } 327 328 331 public boolean isSubtype(String type, String superType) { 332 return cache.isSubtype(type, superType); 333 } 334 335 public void moved(final IResource source, final IResource destination, int depth) throws CoreException { 336 final int count = destination.getFullPath().segmentCount(); 337 338 IResourceVisitor visitor = new IResourceVisitor() { 340 public boolean visit(IResource resource) { 341 Resource r = (Resource) resource; 342 ResourceInfo info = r.getResourceInfo(false, true); 343 MarkerSet markers = info.getMarkers(false); 344 if (markers == null) 345 return true; 346 info.set(ICoreConstants.M_MARKERS_SNAP_DIRTY); 347 IMarkerSetElement[] removed = new IMarkerSetElement[markers.size()]; 348 IMarkerSetElement[] added = new IMarkerSetElement[markers.size()]; 349 IPath path = resource.getFullPath().removeFirstSegments(count); 350 path = source.getFullPath().append(path); 351 IResource sourceChild = workspace.newResource(path, resource.getType()); 352 IMarkerSetElement[] elements = markers.elements(); 353 for (int i = 0; i < elements.length; i++) { 354 MarkerInfo markerInfo = (MarkerInfo) elements[i]; 356 MarkerDelta delta = new MarkerDelta(IResourceDelta.ADDED, resource, markerInfo); 357 added[i] = delta; 358 delta = new MarkerDelta(IResourceDelta.REMOVED, sourceChild, markerInfo); 360 removed[i] = delta; 361 } 362 changedMarkers(resource, added); 363 changedMarkers(sourceChild, removed); 364 return true; 365 } 366 }; 367 destination.accept(visitor, depth, IContainer.INCLUDE_TEAM_PRIVATE_MEMBERS); 368 } 369 370 373 private void recursiveFindMarkers(IPath path, ArrayList list, String type, boolean includeSubtypes, int depth) { 374 ResourceInfo info = workspace.getResourceInfo(path, false, false); 375 if (info == null) 376 return; 377 MarkerSet markers = info.getMarkers(false); 378 379 if (markers != null) { 381 IMarkerSetElement[] matching; 382 if (type == null) 383 matching = markers.elements(); 384 else 385 matching = basicFindMatching(markers, type, includeSubtypes); 386 buildMarkers(matching, path, info.getType(), list); 387 } 388 389 if (depth == IResource.DEPTH_ZERO || info.getType() == IResource.FILE) 391 return; 392 if (depth == IResource.DEPTH_ONE) 393 depth = IResource.DEPTH_ZERO; 394 IPath[] children = workspace.getElementTree().getChildren(path); 395 for (int i = 0; i < children.length; i++) { 396 recursiveFindMarkers(children[i], list, type, includeSubtypes, depth); 397 } 398 } 399 400 403 private int recursiveFindMaxSeverity(IPath path, String type, boolean includeSubtypes, int depth) { 404 ResourceInfo info = workspace.getResourceInfo(path, false, false); 405 if (info == null) 406 return -1; 407 MarkerSet markers = info.getMarkers(false); 408 409 int max = -1; 411 if (markers != null) { 412 max = basicFindMaxSeverity(markers, type, includeSubtypes); 413 if (max >= IMarker.SEVERITY_ERROR) { 414 return max; 415 } 416 } 417 418 if (depth == IResource.DEPTH_ZERO || info.getType() == IResource.FILE) 420 return max; 421 if (depth == IResource.DEPTH_ONE) 422 depth = IResource.DEPTH_ZERO; 423 IPath[] children = workspace.getElementTree().getChildren(path); 424 for (int i = 0; i < children.length; i++) { 425 max = Math.max(max, recursiveFindMaxSeverity(children[i], type, includeSubtypes, depth)); 426 if (max >= IMarker.SEVERITY_ERROR) { 427 break; 428 } 429 } 430 return max; 431 } 432 433 436 private void recursiveRemoveMarkers(final IPath path, String type, boolean includeSubtypes, int depth) { 437 ResourceInfo info = workspace.getResourceInfo(path, false, false); 438 if (info == null) return; 440 IPathRequestor requestor = new IPathRequestor() { 441 public String requestName() { 442 return path.lastSegment(); 443 } 444 445 public IPath requestPath() { 446 return path; 447 } 448 }; 449 basicRemoveMarkers(info, requestor, type, includeSubtypes); 450 if (depth == IResource.DEPTH_ZERO || info.getType() == IResource.FILE) 452 return; 453 if (depth == IResource.DEPTH_ONE) 454 depth = IResource.DEPTH_ZERO; 455 IPath[] children = workspace.getElementTree().getChildren(path); 456 for (int i = 0; i < children.length; i++) { 457 recursiveRemoveMarkers(children[i], type, includeSubtypes, depth); 458 } 459 } 460 461 464 public void removeMarker(IResource resource, long id) { 465 MarkerInfo markerInfo = findMarkerInfo(resource, id); 466 if (markerInfo == null) 467 return; 468 ResourceInfo info = ((Workspace) resource.getWorkspace()).getResourceInfo(resource.getFullPath(), false, true); 469 MarkerSet markers = info.getMarkers(true); 471 int size = markers.size(); 472 markers.remove(markerInfo); 473 info.setMarkers(markers.size() == 0 ? null : markers); 475 if (markers.size() != size) { 477 if (isPersistent(markerInfo)) 478 info.set(ICoreConstants.M_MARKERS_SNAP_DIRTY); 479 IMarkerSetElement[] change = new IMarkerSetElement[] {new MarkerDelta(IResourceDelta.REMOVED, resource, markerInfo)}; 480 changedMarkers(resource, change); 481 } 482 } 483 484 487 public void removeMarkers(IResource resource, int depth) { 488 removeMarkers(resource, null, false, depth); 489 } 490 491 496 public void removeMarkers(IResource target, final String type, final boolean includeSubtypes, int depth) { 497 if (depth == IResource.DEPTH_INFINITE && target.getType() != IResource.FILE) 498 visitorRemoveMarkers(target.getFullPath(), type, includeSubtypes); 499 else 500 recursiveRemoveMarkers(target.getFullPath(), type, includeSubtypes, depth); 501 } 502 503 506 public void resetMarkerDeltas(long startId) { 507 currentDeltas = null; 508 deltaManager.resetDeltas(startId); 509 } 510 511 public void restore(IResource resource, boolean generateDeltas, IProgressMonitor monitor) throws CoreException { 512 restoreFromSave(resource, generateDeltas); 514 restoreFromSnap(resource); 515 } 516 517 protected void restoreFromSave(IResource resource, boolean generateDeltas) throws CoreException { 518 IPath sourceLocation = workspace.getMetaArea().getMarkersLocationFor(resource); 519 IPath tempLocation = workspace.getMetaArea().getBackupLocationFor(sourceLocation); 520 java.io.File sourceFile = new java.io.File (sourceLocation.toOSString()); 521 java.io.File tempFile = new java.io.File (tempLocation.toOSString()); 522 if (!sourceFile.exists() && !tempFile.exists()) 523 return; 524 try { 525 DataInputStream input = new DataInputStream(new SafeFileInputStream(sourceLocation.toOSString(), tempLocation.toOSString())); 526 try { 527 MarkerReader reader = new MarkerReader(workspace); 528 reader.read(input, generateDeltas); 529 } finally { 530 input.close(); 531 } 532 } catch (Exception e) { 533 String msg = NLS.bind(Messages.resources_readMeta, sourceLocation); 535 throw new ResourceException(IResourceStatus.FAILED_READ_METADATA, sourceLocation, msg, e); 536 } 537 } 538 539 protected void restoreFromSnap(IResource resource) { 540 IPath sourceLocation = workspace.getMetaArea().getMarkersSnapshotLocationFor(resource); 541 if (!sourceLocation.toFile().exists()) 542 return; 543 try { 544 DataInputStream input = new DataInputStream(new SafeChunkyInputStream(sourceLocation.toFile())); 545 try { 546 MarkerSnapshotReader reader = new MarkerSnapshotReader(workspace); 547 while (true) 548 reader.read(input); 549 } catch (EOFException eof) { 550 } finally { 552 input.close(); 553 } 554 } catch (Exception e) { 555 String msg = NLS.bind(Messages.resources_readMeta, sourceLocation); 557 Policy.log(new ResourceStatus(IResourceStatus.FAILED_READ_METADATA, sourceLocation, msg, e)); 558 } 559 } 560 561 public void save(ResourceInfo info, IPathRequestor requestor, DataOutputStream output, List list) throws IOException { 562 writer.save(info, requestor, output, list); 563 } 564 565 568 public void shutdown(IProgressMonitor monitor) { 569 } 571 572 public void snap(ResourceInfo info, IPathRequestor requestor, DataOutputStream output) throws IOException { 573 writer.snap(info, requestor, output); 574 } 575 576 579 public void startup(IProgressMonitor monitor) { 580 } 582 583 586 private void visitorFindMarkers(IPath path, final ArrayList list, final String type, final boolean includeSubtypes) { 587 IElementContentVisitor visitor = new IElementContentVisitor() { 588 public boolean visitElement(ElementTree tree, IPathRequestor requestor, Object elementContents) { 589 ResourceInfo info = (ResourceInfo) elementContents; 590 if (info == null) 591 return false; 592 MarkerSet markers = info.getMarkers(false); 593 594 if (markers != null) { 596 IMarkerSetElement[] matching; 597 if (type == null) 598 matching = markers.elements(); 599 else 600 matching = basicFindMatching(markers, type, includeSubtypes); 601 buildMarkers(matching, requestor.requestPath(), info.getType(), list); 602 } 603 return true; 604 } 605 }; 606 new ElementTreeIterator(workspace.getElementTree(), path).iterate(visitor); 607 } 608 609 612 private int visitorFindMaxSeverity(IPath path, final String type, final boolean includeSubtypes) { 613 class MaxSeverityVisitor implements IElementContentVisitor { 614 int max = -1; 615 616 public boolean visitElement(ElementTree tree, IPathRequestor requestor, Object elementContents) { 617 if (max >= IMarker.SEVERITY_ERROR) { 619 return false; 620 } 621 ResourceInfo info = (ResourceInfo) elementContents; 622 if (info == null) 623 return false; 624 MarkerSet markers = info.getMarkers(false); 625 626 if (markers != null) { 628 max = Math.max(max, basicFindMaxSeverity(markers, type, includeSubtypes)); 629 } 630 return max < IMarker.SEVERITY_ERROR; 631 } 632 } 633 MaxSeverityVisitor visitor = new MaxSeverityVisitor(); 634 new ElementTreeIterator(workspace.getElementTree(), path).iterate(visitor); 635 return visitor.max; 636 } 637 638 641 private void visitorRemoveMarkers(IPath path, final String type, final boolean includeSubtypes) { 642 IElementContentVisitor visitor = new IElementContentVisitor() { 643 public boolean visitElement(ElementTree tree, IPathRequestor requestor, Object elementContents) { 644 ResourceInfo info = (ResourceInfo) elementContents; 645 if (info == null) 646 return false; 647 basicRemoveMarkers(info, requestor, type, includeSubtypes); 648 return true; 649 } 650 }; 651 new ElementTreeIterator(workspace.getElementTree(), path).iterate(visitor); 652 } 653 } 654 | Popular Tags |