1 11 package org.eclipse.jdt.internal.core; 12 13 import java.io.BufferedInputStream ; 14 import java.io.BufferedOutputStream ; 15 import java.io.DataInputStream ; 16 import java.io.DataOutputStream ; 17 import java.io.File ; 18 import java.io.FileInputStream ; 19 import java.io.FileOutputStream ; 20 import java.io.IOException ; 21 import java.util.*; 22 23 import org.eclipse.core.resources.*; 24 import org.eclipse.core.runtime.*; 25 import org.eclipse.jdt.core.*; 26 import org.eclipse.jdt.internal.core.util.Util; 27 28 31 public class DeltaProcessingState implements IResourceChangeListener { 32 33 36 public IElementChangedListener[] elementChangedListeners = new IElementChangedListener[5]; 37 public int[] elementChangedListenerMasks = new int[5]; 38 public int elementChangedListenerCount = 0; 39 40 43 public IResourceChangeListener[] preResourceChangeListeners = new IResourceChangeListener[1]; 44 public int[] preResourceChangeEventMasks = new int[1]; 45 public int preResourceChangeListenerCount = 0; 46 47 50 private ThreadLocal deltaProcessors = new ThreadLocal (); 51 52 53 public HashMap roots = new HashMap(); 54 55 57 public HashMap otherRoots = new HashMap(); 58 59 61 public HashMap oldRoots = new HashMap(); 62 63 66 public HashMap oldOtherRoots = new HashMap(); 67 68 69 public HashMap sourceAttachments = new HashMap(); 70 71 72 public HashMap projectDependencies = new HashMap(); 73 74 75 public boolean rootsAreStale = true; 76 77 78 private Set initializingThreads = Collections.synchronizedSet(new HashSet()); 79 80 81 public Hashtable externalTimeStamps; 82 83 84 private HashMap classpathValidations = new HashMap(); 85 86 87 private HashMap projectReferenceChanges= new HashMap(); 88 89 93 private HashSet javaProjectNamesCache; 94 95 99 public synchronized void addElementChangedListener(IElementChangedListener listener, int eventMask) { 100 for (int i = 0; i < this.elementChangedListenerCount; i++){ 101 if (this.elementChangedListeners[i] == listener){ 102 103 int cloneLength = this.elementChangedListenerMasks.length; 106 System.arraycopy(this.elementChangedListenerMasks, 0, this.elementChangedListenerMasks = new int[cloneLength], 0, cloneLength); 107 this.elementChangedListenerMasks[i] |= eventMask; return; 109 } 110 } 111 int length; 113 if ((length = this.elementChangedListeners.length) == this.elementChangedListenerCount){ 114 System.arraycopy(this.elementChangedListeners, 0, this.elementChangedListeners = new IElementChangedListener[length*2], 0, length); 115 System.arraycopy(this.elementChangedListenerMasks, 0, this.elementChangedListenerMasks = new int[length*2], 0, length); 116 } 117 this.elementChangedListeners[this.elementChangedListenerCount] = listener; 118 this.elementChangedListenerMasks[this.elementChangedListenerCount] = eventMask; 119 this.elementChangedListenerCount++; 120 } 121 122 public synchronized void addPreResourceChangedListener(IResourceChangeListener listener, int eventMask) { 123 for (int i = 0; i < this.preResourceChangeListenerCount; i++){ 124 if (this.preResourceChangeListeners[i] == listener) { 125 this.preResourceChangeEventMasks[i] |= eventMask; 126 return; 127 } 128 } 129 int length; 131 if ((length = this.preResourceChangeListeners.length) == this.preResourceChangeListenerCount) { 132 System.arraycopy(this.preResourceChangeListeners, 0, this.preResourceChangeListeners = new IResourceChangeListener[length*2], 0, length); 133 System.arraycopy(this.preResourceChangeEventMasks, 0, this.preResourceChangeEventMasks = new int[length*2], 0, length); 134 } 135 this.preResourceChangeListeners[this.preResourceChangeListenerCount] = listener; 136 this.preResourceChangeEventMasks[this.preResourceChangeListenerCount] = eventMask; 137 this.preResourceChangeListenerCount++; 138 } 139 140 public DeltaProcessor getDeltaProcessor() { 141 DeltaProcessor deltaProcessor = (DeltaProcessor)this.deltaProcessors.get(); 142 if (deltaProcessor != null) return deltaProcessor; 143 deltaProcessor = new DeltaProcessor(this, JavaModelManager.getJavaModelManager()); 144 this.deltaProcessors.set(deltaProcessor); 145 return deltaProcessor; 146 } 147 148 public synchronized ClasspathValidation addClasspathValidation(JavaProject project) { 149 ClasspathValidation validation = (ClasspathValidation) this.classpathValidations.get(project); 150 if (validation == null) { 151 validation = new ClasspathValidation(project); 152 this.classpathValidations.put(project, validation); 153 } 154 return validation; 155 } 156 157 public synchronized void addProjectReferenceChange(JavaProject project, IClasspathEntry[] oldResolvedClasspath) { 158 ProjectReferenceChange change = (ProjectReferenceChange) this.projectReferenceChanges.get(project); 159 if (change == null) { 160 change = new ProjectReferenceChange(project, oldResolvedClasspath); 161 this.projectReferenceChanges.put(project, change); 162 } 163 } 164 165 public void initializeRoots() { 166 167 HashMap newRoots = null; 169 HashMap newOtherRoots = null; 170 HashMap newSourceAttachments = null; 171 HashMap newProjectDependencies = null; 172 if (this.rootsAreStale) { 173 Thread currentThread = Thread.currentThread(); 174 boolean addedCurrentThread = false; 175 try { 176 if (!this.initializingThreads.add(currentThread)) return; 179 addedCurrentThread = true; 180 181 JavaModelManager.getJavaModelManager().batchContainerInitializations = true; 184 185 newRoots = new HashMap(); 186 newOtherRoots = new HashMap(); 187 newSourceAttachments = new HashMap(); 188 newProjectDependencies = new HashMap(); 189 190 IJavaModel model = JavaModelManager.getJavaModelManager().getJavaModel(); 191 IJavaProject[] projects; 192 try { 193 projects = model.getJavaProjects(); 194 } catch (JavaModelException e) { 195 return; 197 } 198 for (int i = 0, length = projects.length; i < length; i++) { 199 JavaProject project = (JavaProject) projects[i]; 200 IClasspathEntry[] classpath; 201 try { 202 classpath = project.getResolvedClasspath(); 203 } catch (JavaModelException e) { 204 continue; 206 } 207 for (int j= 0, classpathLength = classpath.length; j < classpathLength; j++) { 208 IClasspathEntry entry = classpath[j]; 209 if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) { 210 IJavaProject key = model.getJavaProject(entry.getPath().segment(0)); IJavaProject[] dependents = (IJavaProject[]) newProjectDependencies.get(key); 212 if (dependents == null) { 213 dependents = new IJavaProject[] {project}; 214 } else { 215 int dependentsLength = dependents.length; 216 System.arraycopy(dependents, 0, dependents = new IJavaProject[dependentsLength+1], 0, dependentsLength); 217 dependents[dependentsLength] = project; 218 } 219 newProjectDependencies.put(key, dependents); 220 continue; 221 } 222 223 IPath path = entry.getPath(); 225 if (newRoots.get(path) == null) { 226 newRoots.put(path, new DeltaProcessor.RootInfo(project, path, ((ClasspathEntry)entry).fullInclusionPatternChars(), ((ClasspathEntry)entry).fullExclusionPatternChars(), entry.getEntryKind())); 227 } else { 228 ArrayList rootList = (ArrayList)newOtherRoots.get(path); 229 if (rootList == null) { 230 rootList = new ArrayList(); 231 newOtherRoots.put(path, rootList); 232 } 233 rootList.add(new DeltaProcessor.RootInfo(project, path, ((ClasspathEntry)entry).fullInclusionPatternChars(), ((ClasspathEntry)entry).fullExclusionPatternChars(), entry.getEntryKind())); 234 } 235 236 if (entry.getEntryKind() != IClasspathEntry.CPE_LIBRARY) continue; 238 String propertyString = null; 239 try { 240 propertyString = Util.getSourceAttachmentProperty(path); 241 } catch (JavaModelException e) { 242 e.printStackTrace(); 243 } 244 IPath sourceAttachmentPath; 245 if (propertyString != null) { 246 int index= propertyString.lastIndexOf(PackageFragmentRoot.ATTACHMENT_PROPERTY_DELIMITER); 247 sourceAttachmentPath = (index < 0) ? new Path(propertyString) : new Path(propertyString.substring(0, index)); 248 } else { 249 sourceAttachmentPath = entry.getSourceAttachmentPath(); 250 } 251 if (sourceAttachmentPath != null) { 252 newSourceAttachments.put(sourceAttachmentPath, path); 253 } 254 } 255 } 256 } finally { 257 if (addedCurrentThread) { 258 this.initializingThreads.remove(currentThread); 259 } 260 } 261 } 262 synchronized(this) { 263 this.oldRoots = this.roots; 264 this.oldOtherRoots = this.otherRoots; 265 if (this.rootsAreStale && newRoots != null) { this.roots = newRoots; 267 this.otherRoots = newOtherRoots; 268 this.sourceAttachments = newSourceAttachments; 269 this.projectDependencies = newProjectDependencies; 270 this.rootsAreStale = false; 271 } 272 } 273 } 274 275 public synchronized ClasspathValidation[] removeClasspathValidations() { 276 int length = this.classpathValidations.size(); 277 if (length == 0) return null; 278 ClasspathValidation[] validations = new ClasspathValidation[length]; 279 this.classpathValidations.values().toArray(validations); 280 this.classpathValidations.clear(); 281 return validations; 282 } 283 284 public synchronized ProjectReferenceChange[] removeProjectReferenceChanges() { 285 int length = this.projectReferenceChanges.size(); 286 if (length == 0) return null; 287 ProjectReferenceChange[] updates = new ProjectReferenceChange[length]; 288 this.projectReferenceChanges.values().toArray(updates); 289 this.projectReferenceChanges.clear(); 290 return updates; 291 } 292 293 public synchronized void removeElementChangedListener(IElementChangedListener listener) { 294 295 for (int i = 0; i < this.elementChangedListenerCount; i++){ 296 297 if (this.elementChangedListeners[i] == listener){ 298 299 int length = this.elementChangedListeners.length; 301 IElementChangedListener[] newListeners = new IElementChangedListener[length]; 302 System.arraycopy(this.elementChangedListeners, 0, newListeners, 0, i); 303 int[] newMasks = new int[length]; 304 System.arraycopy(this.elementChangedListenerMasks, 0, newMasks, 0, i); 305 306 int trailingLength = this.elementChangedListenerCount - i - 1; 308 if (trailingLength > 0){ 309 System.arraycopy(this.elementChangedListeners, i+1, newListeners, i, trailingLength); 310 System.arraycopy(this.elementChangedListenerMasks, i+1, newMasks, i, trailingLength); 311 } 312 313 this.elementChangedListeners = newListeners; 316 this.elementChangedListenerMasks = newMasks; 317 this.elementChangedListenerCount--; 318 return; 319 } 320 } 321 } 322 323 public synchronized void removePreResourceChangedListener(IResourceChangeListener listener) { 324 325 for (int i = 0; i < this.preResourceChangeListenerCount; i++){ 326 327 if (this.preResourceChangeListeners[i] == listener){ 328 329 int length = this.preResourceChangeListeners.length; 331 IResourceChangeListener[] newListeners = new IResourceChangeListener[length]; 332 int[] newEventMasks = new int[length]; 333 System.arraycopy(this.preResourceChangeListeners, 0, newListeners, 0, i); 334 System.arraycopy(this.preResourceChangeEventMasks, 0, newEventMasks, 0, i); 335 336 int trailingLength = this.preResourceChangeListenerCount - i - 1; 338 if (trailingLength > 0) { 339 System.arraycopy(this.preResourceChangeListeners, i+1, newListeners, i, trailingLength); 340 System.arraycopy(this.preResourceChangeEventMasks, i+1, newEventMasks, i, trailingLength); 341 } 342 343 this.preResourceChangeListeners = newListeners; 346 this.preResourceChangeEventMasks = newEventMasks; 347 this.preResourceChangeListenerCount--; 348 return; 349 } 350 } 351 } 352 353 public void resourceChanged(final IResourceChangeEvent event) { 354 for (int i = 0; i < this.preResourceChangeListenerCount; i++) { 355 final IResourceChangeListener listener = this.preResourceChangeListeners[i]; 357 if ((this.preResourceChangeEventMasks[i] & event.getType()) != 0) 358 SafeRunner.run(new ISafeRunnable() { 359 public void handleException(Throwable exception) { 360 Util.log(exception, "Exception occurred in listener of pre Java resource change notification"); } 362 public void run() throws Exception { 363 listener.resourceChanged(event); 364 } 365 }); 366 } 367 try { 368 getDeltaProcessor().resourceChanged(event); 369 } finally { 370 if (event.getType() == IResourceChangeEvent.POST_CHANGE) { 372 this.deltaProcessors.set(null); 373 } 374 } 375 376 } 377 378 public Hashtable getExternalLibTimeStamps() { 379 if (this.externalTimeStamps == null) { 380 Hashtable timeStamps = new Hashtable(); 381 File timestampsFile = getTimeStampsFile(); 382 DataInputStream in = null; 383 try { 384 in = new DataInputStream (new BufferedInputStream (new FileInputStream (timestampsFile))); 385 int size = in.readInt(); 386 while (size-- > 0) { 387 String key = in.readUTF(); 388 long timestamp = in.readLong(); 389 timeStamps.put(Path.fromPortableString(key), new Long (timestamp)); 390 } 391 } catch (IOException e) { 392 if (timestampsFile.exists()) 393 Util.log(e, "Unable to read external time stamps"); } finally { 395 if (in != null) { 396 try { 397 in.close(); 398 } catch (IOException e) { 399 } 401 } 402 } 403 this.externalTimeStamps = timeStamps; 404 } 405 return this.externalTimeStamps; 406 } 407 408 public IJavaProject findJavaProject(String name) { 409 if (getOldJavaProjecNames().contains(name)) 410 return JavaModelManager.getJavaModelManager().getJavaModel().getJavaProject(name); 411 return null; 412 } 413 414 419 public synchronized HashSet getOldJavaProjecNames() { 420 if (this.javaProjectNamesCache == null) { 421 HashSet result = new HashSet(); 422 IJavaProject[] projects; 423 try { 424 projects = JavaModelManager.getJavaModelManager().getJavaModel().getJavaProjects(); 425 } catch (JavaModelException e) { 426 return this.javaProjectNamesCache; 427 } 428 for (int i = 0, length = projects.length; i < length; i++) { 429 IJavaProject project = projects[i]; 430 result.add(project.getElementName()); 431 } 432 return this.javaProjectNamesCache = result; 433 } 434 return this.javaProjectNamesCache; 435 } 436 437 public synchronized void resetOldJavaProjectNames() { 438 this.javaProjectNamesCache = null; 439 } 440 441 private File getTimeStampsFile() { 442 return JavaCore.getPlugin().getStateLocation().append("externalLibsTimeStamps").toFile(); } 444 445 public void saveExternalLibTimeStamps() throws CoreException { 446 if (this.externalTimeStamps == null) return; 447 File timestamps = getTimeStampsFile(); 448 DataOutputStream out = null; 449 try { 450 out = new DataOutputStream (new BufferedOutputStream (new FileOutputStream (timestamps))); 451 out.writeInt(this.externalTimeStamps.size()); 452 Iterator entries = this.externalTimeStamps.entrySet().iterator(); 453 while (entries.hasNext()) { 454 Map.Entry entry = (Map.Entry) entries.next(); 455 IPath key = (IPath) entry.getKey(); 456 out.writeUTF(key.toPortableString()); 457 Long timestamp = (Long ) entry.getValue(); 458 out.writeLong(timestamp.longValue()); 459 } 460 } catch (IOException e) { 461 IStatus status = new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, IStatus.ERROR, "Problems while saving timestamps", e); throw new CoreException(status); 463 } finally { 464 if (out != null) { 465 try { 466 out.close(); 467 } catch (IOException e) { 468 } 470 } 471 } 472 } 473 474 477 public synchronized void updateRoots(IPath containerPath, IResourceDelta containerDelta, DeltaProcessor deltaProcessor) { 478 Map updatedRoots; 479 Map otherUpdatedRoots; 480 if (containerDelta.getKind() == IResourceDelta.REMOVED) { 481 updatedRoots = this.oldRoots; 482 otherUpdatedRoots = this.oldOtherRoots; 483 } else { 484 updatedRoots = this.roots; 485 otherUpdatedRoots = this.otherRoots; 486 } 487 int containerSegmentCount = containerPath.segmentCount(); 488 boolean containerIsProject = containerSegmentCount == 1; 489 Iterator iterator = updatedRoots.entrySet().iterator(); 490 while (iterator.hasNext()) { 491 Map.Entry entry = (Map.Entry) iterator.next(); 492 IPath path = (IPath) entry.getKey(); 493 if (containerPath.isPrefixOf(path) && !containerPath.equals(path)) { 494 IResourceDelta rootDelta = containerDelta.findMember(path.removeFirstSegments(containerSegmentCount)); 495 if (rootDelta == null) continue; 496 DeltaProcessor.RootInfo rootInfo = (DeltaProcessor.RootInfo) entry.getValue(); 497 498 if (!containerIsProject 499 || !rootInfo.project.getPath().isPrefixOf(path)) { deltaProcessor.updateCurrentDeltaAndIndex(rootDelta, IJavaElement.PACKAGE_FRAGMENT_ROOT, rootInfo); 501 } 502 503 ArrayList rootList = (ArrayList)otherUpdatedRoots.get(path); 504 if (rootList != null) { 505 Iterator otherProjects = rootList.iterator(); 506 while (otherProjects.hasNext()) { 507 rootInfo = (DeltaProcessor.RootInfo)otherProjects.next(); 508 if (!containerIsProject 509 || !rootInfo.project.getPath().isPrefixOf(path)) { deltaProcessor.updateCurrentDeltaAndIndex(rootDelta, IJavaElement.PACKAGE_FRAGMENT_ROOT, rootInfo); 511 } 512 } 513 } 514 } 515 } 516 } 517 518 } 519 | Popular Tags |