1 11 package org.eclipse.jdt.internal.core; 12 13 import java.util.ArrayList ; 14 import java.util.HashMap ; 15 import java.util.HashSet ; 16 import java.util.Iterator ; 17 import java.util.Map ; 18 19 import org.eclipse.core.resources.IFolder; 20 import org.eclipse.core.resources.IResource; 21 import org.eclipse.core.resources.IWorkspace; 22 import org.eclipse.core.resources.ResourcesPlugin; 23 import org.eclipse.core.runtime.CoreException; 24 import org.eclipse.core.runtime.IPath; 25 import org.eclipse.jdt.core.IClasspathEntry; 26 import org.eclipse.jdt.core.IJavaElementDelta; 27 import org.eclipse.jdt.core.IPackageFragment; 28 import org.eclipse.jdt.core.IPackageFragmentRoot; 29 import org.eclipse.jdt.core.JavaModelException; 30 import org.eclipse.jdt.internal.compiler.util.ObjectVector; 31 import org.eclipse.jdt.internal.core.JavaModelManager.PerProjectInfo; 32 import org.eclipse.jdt.internal.core.search.indexing.IndexManager; 33 import org.eclipse.jdt.internal.core.util.Util; 34 35 public class ClasspathChange { 36 public static int NO_DELTA = 0x00; 37 public static int HAS_DELTA = 0x01; 38 public static int HAS_PROJECT_CHANGE = 0x10; 39 40 JavaProject project; 41 IClasspathEntry[] oldRawClasspath; 42 IPath oldOutputLocation; 43 IClasspathEntry[] oldResolvedClasspath; 44 45 public ClasspathChange(JavaProject project, IClasspathEntry[] oldRawClasspath, IPath oldOutputLocation, IClasspathEntry[] oldResolvedClasspath) { 46 this.project = project; 47 this.oldRawClasspath = oldRawClasspath; 48 this.oldOutputLocation = oldOutputLocation; 49 this.oldResolvedClasspath = oldResolvedClasspath; 50 } 51 52 private void addClasspathDeltas(JavaElementDelta delta, IPackageFragmentRoot[] roots, int flag) { 53 for (int i = 0; i < roots.length; i++) { 54 IPackageFragmentRoot root = roots[i]; 55 delta.changed(root, flag); 56 if ((flag & IJavaElementDelta.F_REMOVED_FROM_CLASSPATH) != 0 57 || (flag & IJavaElementDelta.F_SOURCEATTACHED) != 0 58 || (flag & IJavaElementDelta.F_SOURCEDETACHED) != 0){ 59 try { 60 root.close(); 61 } catch (JavaModelException e) { 62 } 64 } 65 } 66 } 67 68 72 private int classpathContains(IClasspathEntry[] list, IClasspathEntry entry) { 73 IPath[] exclusionPatterns = entry.getExclusionPatterns(); 74 IPath[] inclusionPatterns = entry.getInclusionPatterns(); 75 nextEntry: for (int i = 0; i < list.length; i++) { 76 IClasspathEntry other = list[i]; 77 if (other.getContentKind() == entry.getContentKind() 78 && other.getEntryKind() == entry.getEntryKind() 79 && other.isExported() == entry.isExported() 80 && other.getPath().equals(entry.getPath())) { 81 IPath entryOutput = entry.getOutputLocation(); 83 IPath otherOutput = other.getOutputLocation(); 84 if (entryOutput == null) { 85 if (otherOutput != null) 86 continue; 87 } else { 88 if (!entryOutput.equals(otherOutput)) 89 continue; 90 } 91 92 IPath[] otherIncludes = other.getInclusionPatterns(); 94 if (inclusionPatterns != otherIncludes) { 95 if (inclusionPatterns == null) continue; 96 int includeLength = inclusionPatterns.length; 97 if (otherIncludes == null || otherIncludes.length != includeLength) 98 continue; 99 for (int j = 0; j < includeLength; j++) { 100 if (!inclusionPatterns[j].toString().equals(otherIncludes[j].toString())) 103 continue nextEntry; 104 } 105 } 106 IPath[] otherExcludes = other.getExclusionPatterns(); 108 if (exclusionPatterns != otherExcludes) { 109 if (exclusionPatterns == null) continue; 110 int excludeLength = exclusionPatterns.length; 111 if (otherExcludes == null || otherExcludes.length != excludeLength) 112 continue; 113 for (int j = 0; j < excludeLength; j++) { 114 if (!exclusionPatterns[j].toString().equals(otherExcludes[j].toString())) 117 continue nextEntry; 118 } 119 } 120 return i; 121 } 122 } 123 return -1; 124 } 125 126 129 private void collectAllSubfolders(IFolder folder, ArrayList collection) throws JavaModelException { 130 try { 131 IResource[] members= folder.members(); 132 for (int i = 0, max = members.length; i < max; i++) { 133 IResource r= members[i]; 134 if (r.getType() == IResource.FOLDER) { 135 collection.add(r); 136 collectAllSubfolders((IFolder)r, collection); 137 } 138 } 139 } catch (CoreException e) { 140 throw new JavaModelException(e); 141 } 142 } 143 144 150 private ArrayList determineAffectedPackageFragments(IPath location) throws JavaModelException { 151 ArrayList fragments = new ArrayList (); 152 153 IWorkspace workspace = ResourcesPlugin.getWorkspace(); 155 IResource resource = null; 156 if (location != null) { 157 resource = workspace.getRoot().findMember(location); 158 } 159 if (resource != null && resource.getType() == IResource.FOLDER) { 160 IFolder folder = (IFolder) resource; 161 IClasspathEntry[] classpath = this.project.getExpandedClasspath(); 163 for (int i = 0; i < classpath.length; i++) { 164 IClasspathEntry entry = classpath[i]; 165 IPath path = classpath[i].getPath(); 166 if (entry.getEntryKind() != IClasspathEntry.CPE_PROJECT && path.isPrefixOf(location) && !path.equals(location)) { 167 IPackageFragmentRoot[] roots = this.project.computePackageFragmentRoots(classpath[i]); 168 PackageFragmentRoot root = (PackageFragmentRoot) roots[0]; 169 ArrayList folders = new ArrayList (); 171 folders.add(folder); 172 collectAllSubfolders(folder, folders); 173 Iterator elements = folders.iterator(); 174 int segments = path.segmentCount(); 175 while (elements.hasNext()) { 176 IFolder f = (IFolder) elements.next(); 177 IPath relativePath = f.getFullPath().removeFirstSegments(segments); 178 String [] pkgName = relativePath.segments(); 179 IPackageFragment pkg = root.getPackageFragment(pkgName); 180 if (!Util.isExcluded(pkg)) 181 fragments.add(pkg); 182 } 183 } 184 } 185 } 186 return fragments; 187 } 188 189 public boolean equals(Object obj) { 190 if (!(obj instanceof ClasspathChange)) 191 return false; 192 return this.project.equals(((ClasspathChange) obj).project); 193 } 194 195 199 public int generateDelta(JavaElementDelta delta) { 200 JavaModelManager manager = JavaModelManager.getJavaModelManager(); 201 DeltaProcessingState state = manager.deltaState; 202 if (state.findJavaProject(this.project.getElementName()) == null) 203 return NO_DELTA; 207 208 DeltaProcessor deltaProcessor = state.getDeltaProcessor(); 209 IClasspathEntry[] newResolvedClasspath = null; 210 IPath newOutputLocation = null; 211 int result = NO_DELTA; 212 try { 213 PerProjectInfo perProjectInfo = this.project.getPerProjectInfo(); 214 215 this.project.resolveClasspath(perProjectInfo); 217 IClasspathEntry[] newRawClasspath; 218 219 synchronized (perProjectInfo) { 221 newRawClasspath = perProjectInfo.rawClasspath; 222 newResolvedClasspath = perProjectInfo.resolvedClasspath; 223 newOutputLocation = perProjectInfo.outputLocation; 224 } 225 226 if (this.oldRawClasspath != null && !JavaProject.areClasspathsEqual(this.oldRawClasspath, newRawClasspath, this.oldOutputLocation, newOutputLocation)) { 228 delta.changed(this.project, IJavaElementDelta.F_CLASSPATH_CHANGED); 229 result |= HAS_DELTA; 230 } 231 232 if (this.oldResolvedClasspath != null && JavaProject.areClasspathsEqual(this.oldResolvedClasspath, newResolvedClasspath, this.oldOutputLocation, newOutputLocation)) 234 return NO_DELTA; 235 236 this.project.close(); 238 } catch (JavaModelException e) { 239 if (DeltaProcessor.VERBOSE) { 240 e.printStackTrace(); 241 } 242 return NO_DELTA; 244 } 245 246 if (this.oldResolvedClasspath == null) 247 return NO_DELTA; 248 249 Map removedRoots = null; 250 IPackageFragmentRoot[] roots = null; 251 Map allOldRoots ; 252 if ((allOldRoots = deltaProcessor.oldRoots) != null) { 253 roots = (IPackageFragmentRoot[]) allOldRoots.get(this.project); 254 } 255 if (roots != null) { 256 removedRoots = new HashMap (); 257 for (int i = 0; i < roots.length; i++) { 258 IPackageFragmentRoot root = roots[i]; 259 removedRoots.put(root.getPath(), root); 260 } 261 } 262 263 int newLength = newResolvedClasspath.length; 264 int oldLength = this.oldResolvedClasspath.length; 265 for (int i = 0; i < oldLength; i++) { 266 int index = classpathContains(newResolvedClasspath, this.oldResolvedClasspath[i]); 267 if (index == -1) { 268 if (this.oldResolvedClasspath[i].getEntryKind() == IClasspathEntry.CPE_PROJECT) { 270 result |= HAS_PROJECT_CHANGE; 271 continue; 272 } 273 274 IPackageFragmentRoot[] pkgFragmentRoots = null; 275 if (removedRoots != null) { 276 IPackageFragmentRoot oldRoot = (IPackageFragmentRoot) removedRoots.get(this.oldResolvedClasspath[i].getPath()); 277 if (oldRoot != null) { pkgFragmentRoots = new IPackageFragmentRoot[] { oldRoot }; 279 } 280 } 281 if (pkgFragmentRoots == null) { 282 try { 283 ObjectVector accumulatedRoots = new ObjectVector(); 284 HashSet rootIDs = new HashSet (5); 285 rootIDs.add(this.project.rootID()); 286 this.project.computePackageFragmentRoots( 287 this.oldResolvedClasspath[i], 288 accumulatedRoots, 289 rootIDs, 290 null, false, false, null); 294 pkgFragmentRoots = new IPackageFragmentRoot[accumulatedRoots.size()]; 295 accumulatedRoots.copyInto(pkgFragmentRoots); 296 } catch (JavaModelException e) { 297 pkgFragmentRoots = new IPackageFragmentRoot[] {}; 298 } 299 } 300 addClasspathDeltas(delta, pkgFragmentRoots, IJavaElementDelta.F_REMOVED_FROM_CLASSPATH); 301 result |= HAS_DELTA; 302 } else { 303 if (this.oldResolvedClasspath[i].getEntryKind() == IClasspathEntry.CPE_PROJECT) { 305 result |= HAS_PROJECT_CHANGE; 306 continue; 307 } 308 if (index != i) { addClasspathDeltas(delta, this.project.computePackageFragmentRoots(this.oldResolvedClasspath[i]), IJavaElementDelta.F_REORDER); 310 result |= HAS_DELTA; 311 } 312 313 IPath newSourcePath = newResolvedClasspath[index].getSourceAttachmentPath(); 315 int sourceAttachmentFlags = getSourceAttachmentDeltaFlag(this.oldResolvedClasspath[i].getSourceAttachmentPath(), newSourcePath); 316 IPath oldRootPath = this.oldResolvedClasspath[i].getSourceAttachmentRootPath(); 317 IPath newRootPath = newResolvedClasspath[index].getSourceAttachmentRootPath(); 318 int sourceAttachmentRootFlags = getSourceAttachmentDeltaFlag(oldRootPath, newRootPath); 319 int flags = sourceAttachmentFlags | sourceAttachmentRootFlags; 320 if (flags != 0) { 321 addClasspathDeltas(delta, this.project.computePackageFragmentRoots(this.oldResolvedClasspath[i]), flags); 322 result |= HAS_DELTA; 323 } else { 324 if (oldRootPath == null && newRootPath == null) { 325 IPackageFragmentRoot[] computedRoots = this.project.computePackageFragmentRoots(this.oldResolvedClasspath[i]); 328 for (int j = 0; j < computedRoots.length; j++) { 329 IPackageFragmentRoot root = computedRoots[j]; 330 try { 332 root.close(); 333 } catch (JavaModelException e) { 334 } 336 } 337 } 338 } 339 } 340 } 341 342 for (int i = 0; i < newLength; i++) { 343 int index = classpathContains(this.oldResolvedClasspath, newResolvedClasspath[i]); 344 if (index == -1) { 345 if (newResolvedClasspath[i].getEntryKind() == IClasspathEntry.CPE_PROJECT) { 347 result |= HAS_PROJECT_CHANGE; 348 continue; 349 } 350 addClasspathDeltas(delta, this.project.computePackageFragmentRoots(newResolvedClasspath[i]), IJavaElementDelta.F_ADDED_TO_CLASSPATH); 351 result |= HAS_DELTA; 352 } } 354 355 if ((newOutputLocation == null && this.oldOutputLocation != null) 357 || (newOutputLocation != null && !newOutputLocation.equals(this.oldOutputLocation))) { 358 try { 359 ArrayList added= determineAffectedPackageFragments(this.oldOutputLocation); 360 Iterator iter = added.iterator(); 361 while (iter.hasNext()){ 362 IPackageFragment frag= (IPackageFragment)iter.next(); 363 ((IPackageFragmentRoot)frag.getParent()).close(); 364 delta.added(frag); 365 result |= HAS_DELTA; 366 } 367 368 ArrayList removed= determineAffectedPackageFragments(newOutputLocation); 370 iter = removed.iterator(); 371 while (iter.hasNext()) { 372 IPackageFragment frag= (IPackageFragment)iter.next(); 373 ((IPackageFragmentRoot)frag.getParent()).close(); 374 delta.removed(frag); 375 result |= HAS_DELTA; 376 } 377 } catch (JavaModelException e) { 378 if (DeltaProcessor.VERBOSE) 379 e.printStackTrace(); 380 } 381 } 382 383 return result; 384 } 385 386 391 private int getSourceAttachmentDeltaFlag(IPath oldPath, IPath newPath) { 392 if (oldPath == null) { 393 if (newPath != null) { 394 return IJavaElementDelta.F_SOURCEATTACHED; 395 } else { 396 return 0; 397 } 398 } else if (newPath == null) { 399 return IJavaElementDelta.F_SOURCEDETACHED; 400 } else if (!oldPath.equals(newPath)) { 401 return IJavaElementDelta.F_SOURCEATTACHED | IJavaElementDelta.F_SOURCEDETACHED; 402 } else { 403 return 0; 404 } 405 } 406 407 public int hashCode() { 408 return this.project.hashCode(); 409 } 410 411 414 public void requestIndexing() { 415 IClasspathEntry[] newResolvedClasspath = null; 416 try { 417 newResolvedClasspath = this.project.getResolvedClasspath(); 418 } catch (JavaModelException e) { 419 return; 421 } 422 423 JavaModelManager manager = JavaModelManager.getJavaModelManager(); 424 IndexManager indexManager = manager.indexManager; 425 if (indexManager == null) 426 return; 427 DeltaProcessingState state = manager.deltaState; 428 429 int newLength = newResolvedClasspath.length; 430 int oldLength = this.oldResolvedClasspath.length; 431 for (int i = 0; i < oldLength; i++) { 432 int index = classpathContains(newResolvedClasspath, this.oldResolvedClasspath[i]); 433 if (index == -1) { 434 if (this.oldResolvedClasspath[i].getEntryKind() == IClasspathEntry.CPE_PROJECT){ 436 continue; 437 } 438 439 IClasspathEntry oldEntry = this.oldResolvedClasspath[i]; 442 final IPath path = oldEntry.getPath(); 443 int changeKind = this.oldResolvedClasspath[i].getEntryKind(); 444 switch (changeKind) { 445 case IClasspathEntry.CPE_SOURCE: 446 char[][] inclusionPatterns = ((ClasspathEntry)oldEntry).fullInclusionPatternChars(); 447 char[][] exclusionPatterns = ((ClasspathEntry)oldEntry).fullExclusionPatternChars(); 448 indexManager.removeSourceFolderFromIndex(this.project, path, inclusionPatterns, exclusionPatterns); 449 break; 450 case IClasspathEntry.CPE_LIBRARY: 451 if (state.otherRoots.get(path) == null) { indexManager.discardJobs(path.toString()); 453 indexManager.removeIndex(path); 454 } 456 break; 457 } 458 } 459 } 460 461 for (int i = 0; i < newLength; i++) { 462 int index = classpathContains(this.oldResolvedClasspath, newResolvedClasspath[i]); 463 if (index == -1) { 464 if (newResolvedClasspath[i].getEntryKind() == IClasspathEntry.CPE_PROJECT){ 466 continue; 467 } 468 469 int entryKind = newResolvedClasspath[i].getEntryKind(); 471 switch (entryKind) { 472 case IClasspathEntry.CPE_LIBRARY: 473 boolean pathHasChanged = true; 474 IPath newPath = newResolvedClasspath[i].getPath(); 475 for (int j = 0; j < oldLength; j++) { 476 IClasspathEntry oldEntry = this.oldResolvedClasspath[j]; 477 if (oldEntry.getPath().equals(newPath)) { 478 pathHasChanged = false; 479 break; 480 } 481 } 482 if (pathHasChanged) { 483 indexManager.indexLibrary(newPath, this.project.getProject()); 484 } 485 break; 486 case IClasspathEntry.CPE_SOURCE: 487 IClasspathEntry entry = newResolvedClasspath[i]; 488 IPath path = entry.getPath(); 489 char[][] inclusionPatterns = ((ClasspathEntry)entry).fullInclusionPatternChars(); 490 char[][] exclusionPatterns = ((ClasspathEntry)entry).fullExclusionPatternChars(); 491 indexManager.indexSourceFolder(this.project, path, inclusionPatterns, exclusionPatterns); 492 break; 493 } 494 } 495 } 496 } 497 498 public String toString() { 499 return "ClasspathChange: " + this.project.getElementName(); } 501 } 502 | Popular Tags |