Changes:
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / core / DeltaProcessor.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2003 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.html
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package net.sourceforge.phpdt.internal.core;
12
13 import java.io.File;
14 import java.util.ArrayList;
15 import java.util.HashMap;
16 import java.util.HashSet;
17 import java.util.Map;
18
19 import net.sourceforge.phpdt.core.ElementChangedEvent;
20 import net.sourceforge.phpdt.core.IJavaElement;
21 import net.sourceforge.phpdt.core.IJavaProject;
22 import net.sourceforge.phpdt.core.JavaCore;
23 import net.sourceforge.phpdt.core.JavaModelException;
24 import net.sourceforge.phpdt.internal.ui.util.PHPFileUtil;
25
26 import org.eclipse.core.resources.IFile;
27 import org.eclipse.core.resources.IProject;
28 import org.eclipse.core.resources.IResource;
29 import org.eclipse.core.resources.IResourceChangeEvent;
30 import org.eclipse.core.resources.IResourceChangeListener;
31 import org.eclipse.core.resources.IResourceDelta;
32 import org.eclipse.core.resources.IResourceDeltaVisitor;
33 import org.eclipse.core.resources.IWorkspace;
34 import org.eclipse.core.runtime.CoreException;
35 import org.eclipse.core.runtime.IPath;
36
37
38 /**
39  * This class is used by <code>JavaModelManager</code> to convert
40  * <code>IResourceDelta</code>s into <code>IJavaElementDelta</code>s.
41  * It also does some processing on the <code>JavaElement</code>s involved
42  * (e.g. closing them or updating classpaths).
43  */
44 public class DeltaProcessor implements IResourceChangeListener {
45         
46         final static int IGNORE = 0;
47         final static int SOURCE = 1;
48         final static int BINARY = 2;
49         
50         final static String EXTERNAL_JAR_ADDED = "external jar added"; //$NON-NLS-1$
51         final static String EXTERNAL_JAR_REMOVED = "external jar removed"; //$NON-NLS-1$
52         final static String EXTERNAL_JAR_CHANGED = "external jar changed"; //$NON-NLS-1$
53         final static String EXTERNAL_JAR_UNCHANGED = "external jar unchanged"; //$NON-NLS-1$
54         final static String INTERNAL_JAR_IGNORE = "internal jar ignore"; //$NON-NLS-1$
55         
56         final static int NON_JAVA_RESOURCE = -1;
57         
58         /**
59          * The <code>JavaElementDelta</code> corresponding to the <code>IResourceDelta</code> being translated.
60          */
61         protected JavaElementDelta currentDelta;
62         
63 //      protected IndexManager indexManager = new IndexManager();
64                 
65         /* A table from IPath (from a classpath entry) to RootInfo */
66         public Map roots;
67         
68         /* A table from IPath (from a classpath entry) to ArrayList of RootInfo
69          * Used when an IPath corresponds to more than one root */
70         Map otherRoots;
71         
72         /* Whether the roots tables should be recomputed */
73         public boolean rootsAreStale = true;
74         
75         /* A table from IPath (from a classpath entry) to RootInfo
76          * from the last time the delta processor was invoked. */
77         public Map oldRoots;
78
79         /* A table from IPath (from a classpath entry) to ArrayList of RootInfo
80          * from the last time the delta processor was invoked.
81          * Used when an IPath corresponds to more than one root */
82         Map oldOtherRoots;
83         
84         /* A table from IPath (a source attachment path from a classpath entry) to IPath (a root path) */
85         Map sourceAttachments;
86
87         /* The java element that was last created (see createElement(IResource)). 
88          * This is used as a stack of java elements (using getParent() to pop it, and 
89          * using the various get*(...) to push it. */
90         Openable currentElement;
91                 
92         public HashMap externalTimeStamps = new HashMap();
93         public HashSet projectsToUpdate = new HashSet();
94         // list of root projects which namelookup caches need to be updated for dependents
95         // TODO: (jerome) is it needed? projectsToUpdate might be sufficient
96         public HashSet projectsForDependentNamelookupRefresh = new HashSet();  
97         
98         JavaModelManager manager;
99         
100         /* A table from IJavaProject to an array of IPackageFragmentRoot.
101          * This table contains the pkg fragment roots of the project that are being deleted.
102          */
103         Map removedRoots;
104         
105         /*
106          * A list of IJavaElement used as a scope for external archives refresh during POST_CHANGE.
107          * This is null if no refresh is needed.
108          */
109         HashSet refreshedElements;
110         public static boolean VERBOSE = false;
111         
112         class OutputsInfo {
113                 IPath[] paths;
114                 int[] traverseModes;
115                 int outputCount;
116                 OutputsInfo(IPath[] paths, int[] traverseModes, int outputCount) {
117                         this.paths = paths;
118                         this.traverseModes = traverseModes;
119                         this.outputCount = outputCount;
120                 }
121                 public String toString() {
122                         if (this.paths == null) return "<none>"; //$NON-NLS-1$
123                         StringBuffer buffer = new StringBuffer();
124                         for (int i = 0; i < this.outputCount; i++) {
125                                 buffer.append("path="); //$NON-NLS-1$
126                                 buffer.append(this.paths[i].toString());
127                                 buffer.append("\n->traverse="); //$NON-NLS-1$
128                                 switch (this.traverseModes[i]) {
129                                         case BINARY:
130                                                 buffer.append("BINARY"); //$NON-NLS-1$
131                                                 break;
132                                         case IGNORE:
133                                                 buffer.append("IGNORE"); //$NON-NLS-1$
134                                                 break;
135                                         case SOURCE:
136                                                 buffer.append("SOURCE"); //$NON-NLS-1$
137                                                 break;
138                                         default:
139                                                 buffer.append("<unknown>"); //$NON-NLS-1$
140                                 }
141                                 if (i+1 < this.outputCount) {
142                                         buffer.append('\n');
143                                 }
144                         }
145                         return buffer.toString();
146                 }
147         }
148         class RootInfo {
149                 IJavaProject project;
150                 IPath rootPath;
151                 char[][] exclusionPatterns;
152                 RootInfo(IJavaProject project, IPath rootPath, char[][] exclusionPatterns) {
153                         this.project = project;
154                         this.rootPath = rootPath;
155                         this.exclusionPatterns = exclusionPatterns;
156                 }
157                 boolean isRootOfProject(IPath path) {
158                         return this.rootPath.equals(path) && this.project.getProject().getFullPath().isPrefixOf(path);
159                 }
160                 public String toString() {
161                         StringBuffer buffer = new StringBuffer("project="); //$NON-NLS-1$
162                         if (this.project == null) {
163                                 buffer.append("null"); //$NON-NLS-1$
164                         } else {
165                                 buffer.append(this.project.getElementName());
166                         }
167                         buffer.append("\npath="); //$NON-NLS-1$
168                         if (this.rootPath == null) {
169                                 buffer.append("null"); //$NON-NLS-1$
170                         } else {
171                                 buffer.append(this.rootPath.toString());
172                         }
173                         buffer.append("\nexcluding="); //$NON-NLS-1$
174                         if (this.exclusionPatterns == null) {
175                                 buffer.append("null"); //$NON-NLS-1$
176                         } else {
177                                 for (int i = 0, length = this.exclusionPatterns.length; i < length; i++) {
178                                         buffer.append(new String(this.exclusionPatterns[i]));
179                                         if (i < length-1) {
180                                                 buffer.append("|"); //$NON-NLS-1$
181                                         }
182                                 }
183                         }
184                         return buffer.toString();
185                 }
186         }
187
188         DeltaProcessor(JavaModelManager manager) {
189                 this.manager = manager;
190         }
191
192         /*
193          * Adds the dependents of the given project to the list of the projects
194          * to update.
195          */
196 //      void addDependentProjects(IPath projectPath, HashSet result) {
197 //              try {
198 //                      IJavaProject[] projects = this.manager.getJavaModel().getJavaProjects();
199 //                      for (int i = 0, length = projects.length; i < length; i++) {
200 //                              IJavaProject project = projects[i];
201 //                              IClasspathEntry[] classpath = ((JavaProject)project).getExpandedClasspath(true);
202 //                              for (int j = 0, length2 = classpath.length; j < length2; j++) {
203 //                                      IClasspathEntry entry = classpath[j];
204 //                                              if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT
205 //                                                              && entry.getPath().equals(projectPath)) {
206 //                                                      result.add(project);
207 //                                              }
208 //                                      }
209 //                              }
210 //              } catch (JavaModelException e) {
211 //              }
212 //      }
213         /*
214          * Adds the given element to the list of elements used as a scope for external jars refresh.
215          */
216         public void addForRefresh(IJavaElement element) {
217                 if (this.refreshedElements == null) {
218                         this.refreshedElements = new HashSet();
219                 }
220                 this.refreshedElements.add(element);
221         }
222         /*
223          * Adds the given project and its dependents to the list of the projects
224          * to update.
225          */
226         void addToProjectsToUpdateWithDependents(IProject project) {
227                 this.projectsToUpdate.add(JavaCore.create(project));
228 //              this.addDependentProjects(project.getFullPath(), this.projectsToUpdate);
229         }
230         
231         /**
232          * Adds the given child handle to its parent's cache of children. 
233          */
234         protected void addToParentInfo(Openable child) {
235
236                 Openable parent = (Openable) child.getParent();
237                 if (parent != null && parent.isOpen()) {
238                         try {
239                                 JavaElementInfo info = (JavaElementInfo)parent.getElementInfo();
240                                 info.addChild(child);
241                         } catch (JavaModelException e) {
242                                 // do nothing - we already checked if open
243                         }
244                 }
245         }
246
247         /**
248          * Check all external archive (referenced by given roots, projects or model) status and issue a corresponding root delta.
249          * Also triggers index updates
250          */
251 //      public void checkExternalArchiveChanges(IJavaElement[] refreshedElements, IProgressMonitor monitor) throws JavaModelException {
252 //              try {
253 //                      for (int i = 0, length = refreshedElements.length; i < length; i++) {
254 //                              this.addForRefresh(refreshedElements[i]);
255 //                      }
256 //                      boolean hasDelta = this.createExternalArchiveDelta(monitor);
257 //                      if (monitor != null && monitor.isCanceled()) return; 
258 //                      if (hasDelta){
259 //                              // force classpath marker refresh of affected projects
260 //                              JavaModel.flushExternalFileCache();
261 //                              IJavaElementDelta[] projectDeltas = this.currentDelta.getAffectedChildren();
262 //                              for (int i = 0, length = projectDeltas.length; i < length; i++) {
263 //                                      IJavaElementDelta delta = projectDeltas[i];
264 //                                      ((JavaProject)delta.getElement()).getResolvedClasspath(
265 //                                              true, // ignoreUnresolvedEntry
266 //                                              true); // generateMarkerOnError
267 //                              }               
268 //                              if (this.currentDelta != null) { // if delta has not been fired while creating markers
269 //                                      this.manager.fire(this.currentDelta, JavaModelManager.DEFAULT_CHANGE_EVENT);
270 //                              }
271 //                      }
272 //              } finally {
273 //                      this.currentDelta = null;
274 //                      if (monitor != null) monitor.done();
275 //              }
276 //      }
277         /*
278          * Check if external archives have changed and create the corresponding deltas.
279          * Returns whether at least on delta was created.
280          */
281 //      public boolean createExternalArchiveDelta(IProgressMonitor monitor) throws JavaModelException {
282 //              
283 //              if (this.refreshedElements == null) return false;
284 //                      
285 //              HashMap externalArchivesStatus = new HashMap();
286 //              boolean hasDelta = false;
287 //              
288 //              // find JARs to refresh
289 //              HashSet archivePathsToRefresh = new HashSet();
290 //              try {
291 //                      Iterator iterator = this.refreshedElements.iterator();
292 //                      while (iterator.hasNext()) {
293 //                              IJavaElement element = (IJavaElement)iterator.next();
294 //                              switch(element.getElementType()){
295 //                                      case IJavaElement.PACKAGE_FRAGMENT_ROOT :
296 //                                              archivePathsToRefresh.add(element.getPath());
297 //                                              break;
298 //                                      case IJavaElement.JAVA_PROJECT :
299 //                                              IJavaProject project = (IJavaProject) element;
300 //                                              if (!JavaProject.hasJavaNature(project.getProject())) {
301 //                                                      // project is not accessible or has lost its Java nature
302 //                                                      break;
303 //                                              }
304 //                                              IClasspathEntry[] classpath = project.getResolvedClasspath(true);
305 //                                              for (int j = 0, cpLength = classpath.length; j < cpLength; j++){
306 //                                                      if (classpath[j].getEntryKind() == IClasspathEntry.CPE_LIBRARY){
307 //                                                              archivePathsToRefresh.add(classpath[j].getPath());
308 //                                                      }
309 //                                              }
310 //                                              break;
311 //                                      case IJavaElement.JAVA_MODEL :
312 //                                              IJavaProject[] projects = manager.getJavaModel().getOldJavaProjectsList();
313 //                                              for (int j = 0, projectsLength = projects.length; j < projectsLength; j++){
314 //                                                      project = projects[j];
315 //                                                      if (!JavaProject.hasJavaNature(project.getProject())) {
316 //                                                              // project is not accessible or has lost its Java nature
317 //                                                              continue;
318 //                                                      }
319 //                                                      classpath = project.getResolvedClasspath(true);
320 //                                                      for (int k = 0, cpLength = classpath.length; k < cpLength; k++){
321 //                                                              if (classpath[k].getEntryKind() == IClasspathEntry.CPE_LIBRARY){
322 //                                                                      archivePathsToRefresh.add(classpath[k].getPath());
323 //                                                              }
324 //                                                      }
325 //                                              }
326 //                                              break;
327 //                              }
328 //                      }
329 //              } finally {
330 //                      this.refreshedElements = null;
331 //              }
332 //              
333 //              // perform refresh
334 //              IJavaProject[] projects = manager.getJavaModel().getOldJavaProjectsList();
335 //              IWorkspaceRoot wksRoot = ResourcesPlugin.getWorkspace().getRoot();
336 //              for (int i = 0, length = projects.length; i < length; i++) {
337 //                      
338 //                      if (monitor != null && monitor.isCanceled()) break; 
339 //                      
340 //                      IJavaProject project = projects[i];
341 //                      if (!JavaProject.hasJavaNature(project.getProject())) {
342 //                              // project is not accessible or has lost its Java nature
343 //                              continue;
344 //                      }
345 //                      IClasspathEntry[] entries = project.getResolvedClasspath(true);
346 //                      for (int j = 0; j < entries.length; j++){
347 //                              if (entries[j].getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
348 //                                      
349 //                                      IPath entryPath = entries[j].getPath();
350 //                                      
351 //                                      if (!archivePathsToRefresh.contains(entryPath)) continue; // not supposed to be refreshed
352 //                                      
353 //                                      String status = (String)externalArchivesStatus.get(entryPath); 
354 //                                      if (status == null){
355 //                                              
356 //                                              // compute shared status
357 //                                              Object targetLibrary = JavaModel.getTarget(wksRoot, entryPath, true);
358 //              
359 //                                              if (targetLibrary == null){ // missing JAR
360 //                                                      if (this.externalTimeStamps.containsKey(entryPath)){
361 //                                                              this.externalTimeStamps.remove(entryPath);
362 //                                                              externalArchivesStatus.put(entryPath, EXTERNAL_JAR_REMOVED);
363 //                                                              // the jar was physically removed: remove the index
364 //                                                              indexManager.removeIndex(entryPath);
365 //                                                      }
366 //              
367 //                                              } else if (targetLibrary instanceof File){ // external JAR
368 //              
369 //                                                      File externalFile = (File)targetLibrary;
370 //                                                      
371 //                                                      // check timestamp to figure if JAR has changed in some way
372 //                                                      Long oldTimestamp =(Long) this.externalTimeStamps.get(entryPath);
373 //                                                      long newTimeStamp = getTimeStamp(externalFile);
374 //                                                      if (oldTimestamp != null){
375 //              
376 //                                                              if (newTimeStamp == 0){ // file doesn't exist
377 //                                                                      externalArchivesStatus.put(entryPath, EXTERNAL_JAR_REMOVED);
378 //                                                                      this.externalTimeStamps.remove(entryPath);
379 //                                                                      // remove the index
380 //                                                                      indexManager.removeIndex(entryPath);
381 //              
382 //                                                              } else if (oldTimestamp.longValue() != newTimeStamp){
383 //                                                                      externalArchivesStatus.put(entryPath, EXTERNAL_JAR_CHANGED);
384 //                                                                      this.externalTimeStamps.put(entryPath, new Long(newTimeStamp));
385 //                                                                      // first remove the index so that it is forced to be re-indexed
386 //                                                                      indexManager.removeIndex(entryPath);
387 //                                                                      // then index the jar
388 //                                                                      indexManager.indexLibrary(entryPath, project.getProject());
389 //                                                              } else {
390 //                                                                      externalArchivesStatus.put(entryPath, EXTERNAL_JAR_UNCHANGED);
391 //                                                              }
392 //                                                      } else {
393 //                                                              if (newTimeStamp == 0){ // jar still doesn't exist
394 //                                                                      externalArchivesStatus.put(entryPath, EXTERNAL_JAR_UNCHANGED);
395 //                                                              } else {
396 //                                                                      externalArchivesStatus.put(entryPath, EXTERNAL_JAR_ADDED);
397 //                                                                      this.externalTimeStamps.put(entryPath, new Long(newTimeStamp));
398 //                                                                      // index the new jar
399 //                                                                      indexManager.indexLibrary(entryPath, project.getProject());
400 //                                                              }
401 //                                                      }
402 //                                              } else { // internal JAR
403 //                                                      externalArchivesStatus.put(entryPath, INTERNAL_JAR_IGNORE);
404 //                                              }
405 //                                      }
406 //                                      // according to computed status, generate a delta
407 //                                      status = (String)externalArchivesStatus.get(entryPath); 
408 //                                      if (status != null){
409 //                                              if (status == EXTERNAL_JAR_ADDED){
410 //                                                      PackageFragmentRoot root = (PackageFragmentRoot)project.getPackageFragmentRoot(entryPath.toString());
411 //                                                      if (VERBOSE){
412 //                                                              System.out.println("- External JAR ADDED, affecting root: "+root.getElementName()); //$NON-NLS-1$
413 //                                                      } 
414 //                                                      elementAdded(root, null, null);
415 //                                                      hasDelta = true;
416 //                                              } else if (status == EXTERNAL_JAR_CHANGED) {
417 //                                                      PackageFragmentRoot root = (PackageFragmentRoot)project.getPackageFragmentRoot(entryPath.toString());
418 //                                                      if (VERBOSE){
419 //                                                              System.out.println("- External JAR CHANGED, affecting root: "+root.getElementName()); //$NON-NLS-1$
420 //                                                      }
421 //                                                      // reset the corresponding project built state, since the builder would miss this change
422 //                                                      this.manager.setLastBuiltState(project.getProject(), null /*no state*/);
423 //                                                      contentChanged(root, null);
424 //                                                      hasDelta = true;
425 //                                              } else if (status == EXTERNAL_JAR_REMOVED) {
426 //                                                      PackageFragmentRoot root = (PackageFragmentRoot)project.getPackageFragmentRoot(entryPath.toString());
427 //                                                      if (VERBOSE){
428 //                                                              System.out.println("- External JAR REMOVED, affecting root: "+root.getElementName()); //$NON-NLS-1$
429 //                                                      }
430 //                                                      elementRemoved(root, null, null);
431 //                                                      hasDelta = true;
432 //                                              }
433 //                                      }
434 //                              }
435 //                      }
436 //              }
437 //              return hasDelta;
438 //      }
439         JavaElementDelta currentDelta() {
440                 if (this.currentDelta == null) {
441                         this.currentDelta = new JavaElementDelta(this.manager.getJavaModel());
442                 }
443                 return this.currentDelta;
444         }
445         
446         /*
447          * Process the given delta and look for projects being added, opened, closed or
448          * with a java nature being added or removed.
449          * Note that projects being deleted are checked in deleting(IProject).
450          * In all cases, add the project's dependents to the list of projects to update
451          * so that the classpath related markers can be updated.
452          */
453 //      public void checkProjectsBeingAddedOrRemoved(IResourceDelta delta) {
454 //              IResource resource = delta.getResource();
455 //              switch (resource.getType()) {
456 //                      case IResource.ROOT :
457 //                              // workaround for bug 15168 circular errors not reported 
458 //                              if (this.manager.javaProjectsCache == null) {
459 //                                      try {
460 //                                              this.manager.javaProjectsCache = this.manager.getJavaModel().getJavaProjects();
461 //                                      } catch (JavaModelException e) {
462 //                                      }
463 //                              }
464 //                              
465 //                              IResourceDelta[] children = delta.getAffectedChildren();
466 //                              for (int i = 0, length = children.length; i < length; i++) {
467 //                                      this.checkProjectsBeingAddedOrRemoved(children[i]);
468 //                              }
469 //                              break;
470 //                      case IResource.PROJECT :
471 //                              // NB: No need to check project's nature as if the project is not a java project:
472 //                              //     - if the project is added or changed this is a noop for projectsBeingDeleted
473 //                              //     - if the project is closed, it has already lost its java nature
474 //                              int deltaKind = delta.getKind();
475 //                              if (deltaKind == IResourceDelta.ADDED) {
476 //                                      // remember project and its dependents
477 //                                      IProject project = (IProject)resource;
478 //                                      this.addToProjectsToUpdateWithDependents(project);
479 //                                      
480 //                                      // workaround for bug 15168 circular errors not reported 
481 //                                      if (JavaProject.hasJavaNature(project)) {
482 //                                              this.addToParentInfo((JavaProject)JavaCore.create(project));
483 //                                      }
484 //
485 //                              } else if (deltaKind == IResourceDelta.CHANGED) {
486 //                                      IProject project = (IProject)resource;
487 //                                      if ((delta.getFlags() & IResourceDelta.OPEN) != 0) {
488 //                                              // project opened or closed: remember  project and its dependents
489 //                                              this.addToProjectsToUpdateWithDependents(project);
490 //                                              
491 //                                              // workaround for bug 15168 circular errors not reported 
492 //                                              if (project.isOpen()) {
493 //                                                      if (JavaProject.hasJavaNature(project)) {
494 //                                                              this.addToParentInfo((JavaProject)JavaCore.create(project));
495 //                                                      }
496 //                                              } else {
497 //                                                      JavaProject javaProject = (JavaProject)this.manager.getJavaModel().findJavaProject(project);
498 //                                                      if (javaProject != null) {
499 //                                                              try {
500 //                                                                      javaProject.close();
501 //                                                              } catch (JavaModelException e) {
502 //                                                              }
503 //                                                              this.removeFromParentInfo(javaProject);
504 //                                                      }
505 //                                              }
506 //                                      } else if ((delta.getFlags() & IResourceDelta.DESCRIPTION) != 0) {
507 //                                              boolean wasJavaProject = this.manager.getJavaModel().findJavaProject(project) != null;
508 //                                              boolean isJavaProject = JavaProject.hasJavaNature(project);
509 //                                              if (wasJavaProject != isJavaProject) {
510 //                                                      // java nature added or removed: remember  project and its dependents
511 //                                                      this.addToProjectsToUpdateWithDependents(project);
512 //
513 //                                                      // workaround for bug 15168 circular errors not reported 
514 //                                                      if (isJavaProject) {
515 //                                                              this.addToParentInfo((JavaProject)JavaCore.create(project));
516 //                                                      } else {
517 //                                                              JavaProject javaProject = (JavaProject)JavaCore.create(project);
518 //                                                              
519 //                                                              // flush classpath markers
520 //                                                              javaProject.
521 //                                                                      flushClasspathProblemMarkers(
522 //                                                                              true, // flush cycle markers
523 //                                                                              true  //flush classpath format markers
524 //                                                                      );
525 //                                                                      
526 //                                                              // remove problems and tasks created  by the builder
527 //                                                              JavaBuilder.removeProblemsAndTasksFor(project);
528 //
529 //                                                              // close project
530 //                                                              try {
531 //                                                                      javaProject.close();
532 //                                                              } catch (JavaModelException e) {
533 //                                                              }
534 //                                                              this.removeFromParentInfo(javaProject);
535 //                                                      }
536 //                                              } else {
537 //                                                      // in case the project was removed then added then changed (see bug 19799)
538 //                                                      if (JavaProject.hasJavaNature(project)) { // need nature check - 18698
539 //                                                              this.addToParentInfo((JavaProject)JavaCore.create(project));
540 //                                                      }
541 //                                              }
542 //                                      } else {
543 //                                              // workaround for bug 15168 circular errors not reported 
544 //                                              // in case the project was removed then added then changed
545 //                                              if (JavaProject.hasJavaNature(project)) { // need nature check - 18698
546 //                                                      this.addToParentInfo((JavaProject)JavaCore.create(project));
547 //                                              }                                               
548 //                                      }                                       
549 //                              }
550 //                              break;
551 //              }
552 //      }
553
554 //      private void checkSourceAttachmentChange(IResourceDelta delta, IResource res) {
555 //              IPath rootPath = (IPath)this.sourceAttachments.get(res.getFullPath());
556 //              if (rootPath != null) {
557 //                      RootInfo rootInfo = this.rootInfo(rootPath, delta.getKind());
558 //                      if (rootInfo != null) {
559 //                              IJavaProject projectOfRoot = rootInfo.project;
560 //                              IPackageFragmentRoot root = null;
561 //                              try {
562 //                                      // close the root so that source attachement cache is flushed
563 //                                      root = projectOfRoot.findPackageFragmentRoot(rootPath);
564 //                                      if (root != null) {
565 //                                              root.close();
566 //                                      }
567 //                              } catch (JavaModelException e) {
568 //                              }
569 //                              if (root == null) return;
570 //                              switch (delta.getKind()) {
571 //                                      case IResourceDelta.ADDED:
572 //                                              currentDelta().sourceAttached(root);
573 //                                              break;
574 //                                      case IResourceDelta.CHANGED:
575 //                                              currentDelta().sourceDetached(root);
576 //                                              currentDelta().sourceAttached(root);
577 //                                              break;
578 //                                      case IResourceDelta.REMOVED:
579 //                                              currentDelta().sourceDetached(root);
580 //                                              break;
581 //                              }
582 //                      } 
583 //              }
584 //      }
585
586         /**
587          * Closes the given element, which removes it from the cache of open elements.
588          */
589 //      protected static void close(Openable element) {
590 //
591 //              try {
592 //                      element.close();
593 //              } catch (JavaModelException e) {
594 //                      // do nothing
595 //              }
596 //      }
597         /**
598          * Generic processing for elements with changed contents:<ul>
599          * <li>The element is closed such that any subsequent accesses will re-open
600          * the element reflecting its new structure.
601          * <li>An entry is made in the delta reporting a content change (K_CHANGE with F_CONTENT flag set).
602          * </ul>
603          * Delta argument could be null if processing an external JAR change
604          */
605 //      protected void contentChanged(Openable element, IResourceDelta delta) {
606 //
607 //              close(element);
608 //              int flags = IJavaElementDelta.F_CONTENT;
609 //              if (element instanceof JarPackageFragmentRoot){
610 //                      flags |= IJavaElementDelta.F_ARCHIVE_CONTENT_CHANGED;
611 //              }
612 //              currentDelta().changed(element, flags);
613 //      }
614 //      
615         /**
616          * Creates the openables corresponding to this resource.
617          * Returns null if none was found.
618          */
619 //      protected Openable createElement(IResource resource, int elementType, RootInfo rootInfo) {
620 //              if (resource == null) return null;
621 //              
622 //              IPath path = resource.getFullPath();
623 //              IJavaElement element = null;
624 //              switch (elementType) {
625 //                      
626 //                      case IJavaElement.JAVA_PROJECT:
627 //                      
628 //                              // note that non-java resources rooted at the project level will also enter this code with
629 //                              // an elementType JAVA_PROJECT (see #elementType(...)).
630 //                              if (resource instanceof IProject){
631 //
632 //                                      this.popUntilPrefixOf(path);
633 //                                      
634 //                                      if (this.currentElement != null 
635 //                                              && this.currentElement.getElementType() == IJavaElement.JAVA_PROJECT
636 //                                              && ((IJavaProject)this.currentElement).getProject().equals(resource)) {
637 //                                              return this.currentElement;
638 //                                      }
639 //                                      if  (rootInfo != null && rootInfo.project.getProject().equals(resource)){
640 //                                              element = (Openable)rootInfo.project;
641 //                                              break;
642 //                                      }
643 //                                      IProject proj = (IProject)resource;
644 //                                      if (JavaProject.hasJavaNature(proj)) {
645 //                                              element = JavaCore.create(proj);
646 //                                      } else {
647 //                                              // java project may have been been closed or removed (look for
648 //                                              // element amongst old java project s list).
649 //                                              element =  (Openable) manager.getJavaModel().findJavaProject(proj);
650 //                                      }
651 //                              }
652 //                              break;
653 //                      case IJavaElement.PACKAGE_FRAGMENT_ROOT:
654 //                              element = rootInfo == null ? JavaCore.create(resource) : rootInfo.project.getPackageFragmentRoot(resource);
655 //                              break;
656 //                      case IJavaElement.PACKAGE_FRAGMENT:
657 //                              // find the element that encloses the resource
658 //                              this.popUntilPrefixOf(path);
659 //                              
660 //                              if (this.currentElement == null) {
661 //                                      element = rootInfo == null ? JavaCore.create(resource) : JavaModelManager.create(resource, rootInfo.project);
662 //                              } else {
663 //                                      // find the root
664 //                                      IPackageFragmentRoot root = this.currentElement.getPackageFragmentRoot();
665 //                                      if (root == null) {
666 //                                              element =  rootInfo == null ? JavaCore.create(resource) : JavaModelManager.create(resource, rootInfo.project);
667 //                                      } else if (((JavaProject)root.getJavaProject()).contains(resource)) {
668 //                                              // create package handle
669 //                                              IPath pkgPath = path.removeFirstSegments(root.getPath().segmentCount());
670 //                                              String pkg = Util.packageName(pkgPath);
671 //                                              if (pkg == null) return null;
672 //                                              element = root.getPackageFragment(pkg);
673 //                                      }
674 //                              }
675 //                              break;
676 //                      case IJavaElement.COMPILATION_UNIT:
677 //                      case IJavaElement.CLASS_FILE:
678 //                              // find the element that encloses the resource
679 //                              this.popUntilPrefixOf(path);
680 //                              
681 //                              if (this.currentElement == null) {
682 //                                      element =  rootInfo == null ? JavaCore.create(resource) : JavaModelManager.create(resource, rootInfo.project);
683 //                              } else {
684 //                                      // find the package
685 //                                      IPackageFragment pkgFragment = null;
686 //                                      switch (this.currentElement.getElementType()) {
687 //                                              case IJavaElement.PACKAGE_FRAGMENT_ROOT:
688 //                                                      IPackageFragmentRoot root = (IPackageFragmentRoot)this.currentElement;
689 //                                                      IPath rootPath = root.getPath();
690 //                                                      IPath pkgPath = path.removeLastSegments(1);
691 //                                                      String pkgName = Util.packageName(pkgPath.removeFirstSegments(rootPath.segmentCount()));
692 //                                                      if (pkgName != null) {
693 //                                                              pkgFragment = root.getPackageFragment(pkgName);
694 //                                                      }
695 //                                                      break;
696 //                                              case IJavaElement.PACKAGE_FRAGMENT:
697 //                                                      Openable pkg = (Openable)this.currentElement;
698 //                                                      if (pkg.getPath().equals(path.removeLastSegments(1))) {
699 //                                                              pkgFragment = (IPackageFragment)pkg;
700 //                                                      } // else case of package x which is a prefix of x.y
701 //                                                      break;
702 //                                              case IJavaElement.COMPILATION_UNIT:
703 //                                              case IJavaElement.CLASS_FILE:
704 //                                                      pkgFragment = (IPackageFragment)this.currentElement.getParent();
705 //                                                      break;
706 //                                      }
707 //                                      if (pkgFragment == null) {
708 //                                              element =  rootInfo == null ? JavaCore.create(resource) : JavaModelManager.create(resource, rootInfo.project);
709 //                                      } else {
710 //                                              if (elementType == IJavaElement.COMPILATION_UNIT) {
711 //                                                      // create compilation unit handle 
712 //                                                      // fileName validation has been done in elementType(IResourceDelta, int, boolean)
713 //                                                      String fileName = path.lastSegment();
714 //                                                      element = pkgFragment.getCompilationUnit(fileName);
715 //                                              } else {
716 //                                                      // create class file handle
717 //                                                      // fileName validation has been done in elementType(IResourceDelta, int, boolean)
718 //                                                      String fileName = path.lastSegment();
719 //                                                      element = pkgFragment.getClassFile(fileName);
720 //                                              }
721 //                                      }
722 //                              }
723 //                              break;
724 //              }
725 //              if (element == null) {
726 //                      return null;
727 //              } else {
728 //                      this.currentElement = (Openable)element;
729 //                      return this.currentElement;
730 //              }
731 //      }
732         /**
733          * Note that the project is about to be deleted.
734          */
735 //      public void deleting(IProject project) {
736 //              
737 //              try {
738 //                      // discard indexing jobs that belong to this project so that the project can be 
739 //                      // deleted without interferences from the index manager
740 //                      this.indexManager.discardJobs(project.getName());
741 //
742 //                      JavaProject javaProject = (JavaProject)JavaCore.create(project);
743 //                      
744 //                      // remember roots of this project
745 //                      if (this.removedRoots == null) {
746 //                              this.removedRoots = new HashMap();
747 //                      }
748 //                      if (javaProject.isOpen()) {
749 //                              this.removedRoots.put(javaProject, javaProject.getPackageFragmentRoots());
750 //                      } else {
751 //                              // compute roots without opening project
752 //                              this.removedRoots.put(
753 //                                      javaProject, 
754 //                                      javaProject.computePackageFragmentRoots(
755 //                                              javaProject.getResolvedClasspath(true), 
756 //                                              false));
757 //                      }
758 //                      
759 //                      javaProject.close();
760 //
761 //                      // workaround for bug 15168 circular errors not reported  
762 //                      if (this.manager.javaProjectsCache == null) {
763 //                              this.manager.javaProjectsCache = this.manager.getJavaModel().getJavaProjects();
764 //                      }
765 //                      this.removeFromParentInfo(javaProject);
766 //
767 //              } catch (JavaModelException e) {
768 //              }
769 //              
770 //              this.addDependentProjects(project.getFullPath(), this.projectsToUpdate);
771 //      }
772
773
774         /**
775          * Processing for an element that has been added:<ul>
776          * <li>If the element is a project, do nothing, and do not process
777          * children, as when a project is created it does not yet have any
778          * natures - specifically a java nature.
779          * <li>If the elemet is not a project, process it as added (see
780          * <code>basicElementAdded</code>.
781          * </ul>
782          * Delta argument could be null if processing an external JAR change
783          */
784 //      protected void elementAdded(Openable element, IResourceDelta delta, RootInfo rootInfo) {
785 //              int elementType = element.getElementType();
786 //              
787 //              if (elementType == IJavaElement.JAVA_PROJECT) {
788 //                      // project add is handled by JavaProject.configure() because
789 //                      // when a project is created, it does not yet have a java nature
790 //                      if (delta != null && JavaProject.hasJavaNature((IProject)delta.getResource())) {
791 //                              addToParentInfo(element);
792 //                              if ((delta.getFlags() & IResourceDelta.MOVED_FROM) != 0) {
793 //                                      Openable movedFromElement = (Openable)element.getJavaModel().getJavaProject(delta.getMovedFromPath().lastSegment());
794 //                                      currentDelta().movedTo(element, movedFromElement);
795 //                              } else {
796 //                                      currentDelta().added(element);
797 //                              }
798 //                              this.projectsToUpdate.add(element);
799 //                              this.updateRoots(element.getPath(), delta);
800 //                              this.projectsForDependentNamelookupRefresh.add((JavaProject) element);
801 //                      }
802 //              } else {                        
803 //                      addToParentInfo(element);
804 //                      
805 //                      // Force the element to be closed as it might have been opened 
806 //                      // before the resource modification came in and it might have a new child
807 //                      // For example, in an IWorkspaceRunnable:
808 //                      // 1. create a package fragment p using a java model operation
809 //                      // 2. open package p
810 //                      // 3. add file X.java in folder p
811 //                      // When the resource delta comes in, only the addition of p is notified, 
812 //                      // but the package p is already opened, thus its children are not recomputed
813 //                      // and it appears empty.
814 //                      close(element);
815 //                      
816 //                      if (delta != null && (delta.getFlags() & IResourceDelta.MOVED_FROM) != 0) {
817 //                              IPath movedFromPath = delta.getMovedFromPath();
818 //                              IResource res = delta.getResource();
819 //                              IResource movedFromRes;
820 //                              if (res instanceof IFile) {
821 //                                      movedFromRes = res.getWorkspace().getRoot().getFile(movedFromPath);
822 //                              } else {
823 //                                      movedFromRes = res.getWorkspace().getRoot().getFolder(movedFromPath);
824 //                              }
825 //                              
826 //                              // find the element type of the moved from element
827 //                              RootInfo movedFromInfo = this.enclosingRootInfo(movedFromPath, IResourceDelta.REMOVED);
828 //                              int movedFromType = 
829 //                                      this.elementType(
830 //                                              movedFromRes, 
831 //                                              IResourceDelta.REMOVED,
832 //                                              element.getParent().getElementType(), 
833 //                                              movedFromInfo);
834 //                              
835 //                              // reset current element as it might be inside a nested root (popUntilPrefixOf() may use the outer root)
836 //                              this.currentElement = null;
837 //                      
838 //                              // create the moved from element
839 //                              Openable movedFromElement = 
840 //                                      elementType != IJavaElement.JAVA_PROJECT && movedFromType == IJavaElement.JAVA_PROJECT ? 
841 //                                              null : // outside classpath
842 //                                              this.createElement(movedFromRes, movedFromType, movedFromInfo);
843 //                              if (movedFromElement == null) {
844 //                                      // moved from outside classpath
845 //                                      currentDelta().added(element);
846 //                              } else {
847 //                                      currentDelta().movedTo(element, movedFromElement);
848 //                              }
849 //                      } else {
850 //                              currentDelta().added(element);
851 //                      }
852 //                      
853 //                      switch (elementType) {
854 //                              case IJavaElement.PACKAGE_FRAGMENT_ROOT :
855 //                                      // when a root is added, and is on the classpath, the project must be updated
856 //                                      JavaProject project = (JavaProject) element.getJavaProject();
857 //                                      this.projectsToUpdate.add(project);
858 //                                      this.projectsForDependentNamelookupRefresh.add(project);
859 //                                      
860 //                                      break;
861 //                              case IJavaElement.PACKAGE_FRAGMENT :
862 //                                      // get rid of namelookup since it holds onto obsolete cached info 
863 //                                      project = (JavaProject) element.getJavaProject();
864 //                                      try {
865 //                                              project.getJavaProjectElementInfo().setNameLookup(null);
866 //                                              this.projectsForDependentNamelookupRefresh.add(project);                                                
867 //                                      } catch (JavaModelException e) {
868 //                                      }
869 //                                      // add subpackages
870 //                                      if (delta != null){
871 //                                              PackageFragmentRoot root = element.getPackageFragmentRoot();
872 //                                              String name = element.getElementName();
873 //                                              IResourceDelta[] children = delta.getAffectedChildren();
874 //                                              for (int i = 0, length = children.length; i < length; i++) {
875 //                                                      IResourceDelta child = children[i];
876 //                                                      IResource resource = child.getResource();
877 //                                                      if (resource instanceof IFolder) {
878 //                                                              String folderName = resource.getName();
879 //                                                              if (Util.isValidFolderNameForPackage(folderName)) {
880 //                                                                      String subpkgName = 
881 //                                                                              name.length() == 0 ? 
882 //                                                                                      folderName : 
883 //                                                                                      name + "." + folderName; //$NON-NLS-1$
884 //                                                                      Openable subpkg = (Openable)root.getPackageFragment(subpkgName);
885 //                                                                      this.updateIndex(subpkg, child);
886 //                                                                      this.elementAdded(subpkg, child, rootInfo);
887 //                                                              }
888 //                                                      }
889 //                                              }
890 //                                      }
891 //                                      break;
892 //                      }
893 //              }
894 //      }
895
896         /**
897          * Generic processing for a removed element:<ul>
898          * <li>Close the element, removing its structure from the cache
899          * <li>Remove the element from its parent's cache of children
900          * <li>Add a REMOVED entry in the delta
901          * </ul>
902          * Delta argument could be null if processing an external JAR change
903          */
904 //      protected void elementRemoved(Openable element, IResourceDelta delta, RootInfo rootInfo) {
905 //              
906 //              if (element.isOpen()) {
907 //                      close(element);
908 //              }
909 //              removeFromParentInfo(element);
910 //              int elementType = element.getElementType();
911 //              if (delta != null && (delta.getFlags() & IResourceDelta.MOVED_TO) != 0) {
912 //                      IPath movedToPath = delta.getMovedToPath();
913 //                      IResource res = delta.getResource();
914 //                      IResource movedToRes;
915 //                      switch (res.getType()) {
916 //                              case IResource.PROJECT:
917 //                                      movedToRes = res.getWorkspace().getRoot().getProject(movedToPath.lastSegment());
918 //                                      break;
919 //                              case IResource.FOLDER:
920 //                                      movedToRes = res.getWorkspace().getRoot().getFolder(movedToPath);
921 //                                      break;
922 //                              case IResource.FILE:
923 //                                      movedToRes = res.getWorkspace().getRoot().getFile(movedToPath);
924 //                                      break;
925 //                              default:
926 //                                      return;
927 //                      }
928 //
929 //                      // find the element type of the moved from element
930 //                      RootInfo movedToInfo = this.enclosingRootInfo(movedToPath, IResourceDelta.ADDED);
931 //                      int movedToType = 
932 //                              this.elementType(
933 //                                      movedToRes, 
934 //                                      IResourceDelta.ADDED,
935 //                                      element.getParent().getElementType(), 
936 //                                      movedToInfo);
937 //
938 //                      // reset current element as it might be inside a nested root (popUntilPrefixOf() may use the outer root)
939 //                      this.currentElement = null;
940 //                      
941 //                      // create the moved To element
942 //                      Openable movedToElement = 
943 //                              elementType != IJavaElement.JAVA_PROJECT && movedToType == IJavaElement.JAVA_PROJECT ? 
944 //                                      null : // outside classpath
945 //                                      this.createElement(movedToRes, movedToType, movedToInfo);
946 //                      if (movedToElement == null) {
947 //                              // moved outside classpath
948 //                              currentDelta().removed(element);
949 //                      } else {
950 //                              currentDelta().movedFrom(element, movedToElement);
951 //                      }
952 //              } else {
953 //                      currentDelta().removed(element);
954 //              }
955 //
956 //              switch (elementType) {
957 //                      case IJavaElement.JAVA_MODEL :
958 //                              this.indexManager.reset();
959 //                              break;
960 //                      case IJavaElement.JAVA_PROJECT :
961 //                              this.manager.removePerProjectInfo(
962 //                                      (JavaProject) element);
963 //                              this.updateRoots(element.getPath(), delta);
964 //                              this.projectsForDependentNamelookupRefresh.add((JavaProject) element);
965 //                              break;
966 //                      case IJavaElement.PACKAGE_FRAGMENT_ROOT :
967 //                              JavaProject project = (JavaProject) element.getJavaProject();
968 //                              this.projectsToUpdate.add(project);
969 //                              this.projectsForDependentNamelookupRefresh.add(project);                                
970 //                              break;
971 //                      case IJavaElement.PACKAGE_FRAGMENT :
972 //                              //1G1TW2T - get rid of namelookup since it holds onto obsolete cached info 
973 //                              project = (JavaProject) element.getJavaProject();
974 //                              try {
975 //                                      project.getJavaProjectElementInfo().setNameLookup(null); 
976 //                                      this.projectsForDependentNamelookupRefresh.add(project);
977 //                              } catch (JavaModelException e) { 
978 //                              }
979 //                              // remove subpackages
980 //                              if (delta != null){
981 //                                      PackageFragmentRoot root = element.getPackageFragmentRoot();
982 //                                      String name = element.getElementName();
983 //                                      IResourceDelta[] children = delta.getAffectedChildren();
984 //                                      for (int i = 0, length = children.length; i < length; i++) {
985 //                                              IResourceDelta child = children[i];
986 //                                              IResource resource = child.getResource();
987 //                                              if (resource instanceof IFolder) {
988 //                                                      String folderName = resource.getName();
989 //                                                      if (Util.isValidFolderNameForPackage(folderName)) {
990 //                                                              String subpkgName = 
991 //                                                                      name.length() == 0 ? 
992 //                                                                              folderName : 
993 //                                                                              name + "." + folderName; //$NON-NLS-1$
994 //                                                              Openable subpkg = (Openable)root.getPackageFragment(subpkgName);
995 //                                                              this.updateIndex(subpkg, child);
996 //                                                              this.elementRemoved(subpkg, child, rootInfo);
997 //                                                      }
998 //                                              }
999 //                                      }
1000 //                              }
1001 //                              break;
1002 //              }
1003 //      }
1004
1005         /*
1006          * Returns the type of the java element the given delta matches to.
1007          * Returns NON_JAVA_RESOURCE if unknown (e.g. a non-java resource or excluded .java file)
1008          */
1009 //      private int elementType(IResource res, int kind, int parentType, RootInfo rootInfo) {
1010 //              switch (parentType) {
1011 //                      case IJavaElement.JAVA_MODEL:
1012 //                              // case of a movedTo or movedFrom project (other cases are handled in processResourceDelta(...)
1013 //                              return IJavaElement.JAVA_PROJECT;
1014 //                      case NON_JAVA_RESOURCE:
1015 //                      case IJavaElement.JAVA_PROJECT:
1016 //                              if (rootInfo == null) {
1017 //                                      rootInfo = this.enclosingRootInfo(res.getFullPath(), kind);
1018 //                              }
1019 //                              if (rootInfo != null && rootInfo.isRootOfProject(res.getFullPath())) {
1020 //                                      return IJavaElement.PACKAGE_FRAGMENT_ROOT;
1021 //                              } else {
1022 //                                      return NON_JAVA_RESOURCE; // not yet in a package fragment root or root of another project
1023 //                              }
1024 //                      case IJavaElement.PACKAGE_FRAGMENT_ROOT:
1025 //                      case IJavaElement.PACKAGE_FRAGMENT:
1026 //                              if (rootInfo == null) {
1027 //                                      rootInfo = this.enclosingRootInfo(res.getFullPath(), kind);
1028 //                              }
1029 //                              if (rootInfo == null || Util.isExcluded(res, rootInfo.exclusionPatterns)) {
1030 //                                      return NON_JAVA_RESOURCE;
1031 //                              }
1032 //                              if (res instanceof IFolder) {
1033 //                                      if (Util.isValidFolderNameForPackage(res.getName())) {
1034 //                                              return IJavaElement.PACKAGE_FRAGMENT;
1035 //                                      } else {
1036 //                                              return NON_JAVA_RESOURCE;
1037 //                                      }
1038 //                              } else {
1039 //                                      String fileName = res.getName();
1040 //                                      if (Util.isValidCompilationUnitName(fileName)) {
1041 //                                              return IJavaElement.COMPILATION_UNIT;
1042 //                                      } else if (Util.isValidClassFileName(fileName)) {
1043 //                                              return IJavaElement.CLASS_FILE;
1044 //                                      } else if (this.rootInfo(res.getFullPath(), kind) != null) {
1045 //                                              // case of proj=src=bin and resource is a jar file on the classpath
1046 //                                              return IJavaElement.PACKAGE_FRAGMENT_ROOT;
1047 //                                      } else {
1048 //                                              return NON_JAVA_RESOURCE;
1049 //                                      }
1050 //                              }
1051 //                      default:
1052 //                              return NON_JAVA_RESOURCE;
1053 //              }
1054 //      }
1055
1056         /**
1057          * Answer a combination of the lastModified stamp and the size.
1058          * Used for detecting external JAR changes
1059          */
1060         public static long getTimeStamp(File file) {
1061                 return file.lastModified() + file.length();
1062         }
1063
1064 //      public void initializeRoots() {
1065 //              // remember roots infos as old roots infos
1066 //              this.oldRoots = this.roots == null ? new HashMap() : this.roots;
1067 //              this.oldOtherRoots = this.otherRoots == null ? new HashMap() : this.otherRoots;
1068 //              
1069 //              // recompute root infos only if necessary
1070 //              if (!rootsAreStale) return;
1071 //
1072 //              this.roots = new HashMap();
1073 //              this.otherRoots = new HashMap();
1074 //              this.sourceAttachments = new HashMap();
1075 //              
1076 //              IJavaModel model = this.manager.getJavaModel();
1077 //              IJavaProject[] projects;
1078 //              try {
1079 //                      projects = model.getJavaProjects();
1080 //              } catch (JavaModelException e) {
1081 //                      // nothing can be done
1082 //                      return;
1083 //              }
1084 //              for (int i = 0, length = projects.length; i < length; i++) {
1085 //                      IJavaProject project = projects[i];
1086 //                      IClasspathEntry[] classpath;
1087 //                      try {
1088 //                              classpath = project.getResolvedClasspath(true);
1089 //                      } catch (JavaModelException e) {
1090 //                              // continue with next project
1091 //                              continue;
1092 //                      }
1093 //                      for (int j= 0, classpathLength = classpath.length; j < classpathLength; j++) {
1094 //                              IClasspathEntry entry = classpath[j];
1095 //                              if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) continue;
1096 //                              
1097                                 // root path
1098 //                              IPath path = entry.getPath();
1099 //                              if (this.roots.get(path) == null) {
1100 //                                      this.roots.put(path, new RootInfo(project, path, ((ClasspathEntry)entry).fullExclusionPatternChars()));
1101 //                              } else {
1102 //                                      ArrayList rootList = (ArrayList)this.otherRoots.get(path);
1103 //                                      if (rootList == null) {
1104 //                                              rootList = new ArrayList();
1105 //                                              this.otherRoots.put(path, rootList);
1106 //                                      }
1107 //                                      rootList.add(new RootInfo(project, path, ((ClasspathEntry)entry).fullExclusionPatternChars()));
1108 //                              }
1109 //                              
1110 //                              // source attachment path
1111 //                              if (entry.getEntryKind() != IClasspathEntry.CPE_LIBRARY) continue;
1112 //                              QualifiedName qName = new QualifiedName(JavaCore.PLUGIN_ID, "sourceattachment: " + path.toOSString()); //$NON-NLS-1$;
1113 //                              String propertyString = null;
1114 //                              try {
1115 //                                      propertyString = ResourcesPlugin.getWorkspace().getRoot().getPersistentProperty(qName);
1116 //                              } catch (CoreException e) {
1117 //                                      continue;
1118 //                              }
1119 //                              IPath sourceAttachmentPath;
1120 //                              if (propertyString != null) {
1121 //                                      int index= propertyString.lastIndexOf(JarPackageFragmentRoot.ATTACHMENT_PROPERTY_DELIMITER);
1122 //                                      sourceAttachmentPath = (index < 0) ?  new Path(propertyString) : new Path(propertyString.substring(0, index));
1123 //                              } else {
1124 //                                      sourceAttachmentPath = entry.getSourceAttachmentPath();
1125 //                              }
1126 //                              if (sourceAttachmentPath != null) {
1127 //                                      this.sourceAttachments.put(sourceAttachmentPath, path);
1128 //                              }
1129 //                      }
1130 //              }
1131 //              this.rootsAreStale = false;
1132 //      }
1133
1134         /*
1135          * Returns whether a given delta contains some information relevant to the JavaModel,
1136          * in particular it will not consider SYNC or MARKER only deltas.
1137          */
1138         public boolean isAffectedBy(IResourceDelta rootDelta){
1139                 //if (rootDelta == null) System.out.println("NULL DELTA");
1140                 //long start = System.currentTimeMillis();
1141                 if (rootDelta != null) {
1142                         // use local exception to quickly escape from delta traversal
1143                         class FoundRelevantDeltaException extends RuntimeException {}
1144                         try {
1145                                 rootDelta.accept(new IResourceDeltaVisitor() {
1146                                         public boolean visit(IResourceDelta delta) throws CoreException {
1147                                                 switch (delta.getKind()){
1148                                                         case IResourceDelta.ADDED :
1149                                                         case IResourceDelta.REMOVED :
1150                                                                 throw new FoundRelevantDeltaException();
1151                                                         case IResourceDelta.CHANGED :
1152                                                                 // if any flag is set but SYNC or MARKER, this delta should be considered
1153                                                                 if (delta.getAffectedChildren().length == 0 // only check leaf delta nodes
1154                                                                                 && (delta.getFlags() & ~(IResourceDelta.SYNC | IResourceDelta.MARKERS)) != 0) {
1155                                                                         throw new FoundRelevantDeltaException();
1156                                                                 }
1157                                                 }
1158                                                 return true;
1159                                         }
1160                                 });
1161                         } catch(FoundRelevantDeltaException e) {
1162                                 //System.out.println("RELEVANT DELTA detected in: "+ (System.currentTimeMillis() - start));
1163                                 return true;
1164                         } catch(CoreException e) { // ignore delta if not able to traverse
1165                         }
1166                 }
1167                 //System.out.println("IGNORE SYNC DELTA took: "+ (System.currentTimeMillis() - start));
1168                 return false;
1169         }
1170         
1171         /*
1172          * Returns whether the given resource is in one of the given output folders and if
1173          * it is filtered out from this output folder.
1174          */
1175         private boolean isResFilteredFromOutput(OutputsInfo info, IResource res, int elementType) {
1176                 if (info != null) {
1177                         IPath resPath = res.getFullPath();
1178                         for (int i = 0;  i < info.outputCount; i++) {
1179                                 if (info.paths[i].isPrefixOf(resPath)) {
1180                                         if (info.traverseModes[i] != IGNORE) {
1181                                                 // case of bin=src
1182                                                 if (info.traverseModes[i] == SOURCE && elementType == IJavaElement.CLASS_FILE) {
1183                                                         return true;
1184                                                 } else {
1185                                                         // case of .class file under project and no source folder
1186                                                         // proj=bin
1187                                                         if (elementType == IJavaElement.JAVA_PROJECT 
1188                                                                         && res instanceof IFile 
1189                                                                         && PHPFileUtil.isPHPFile((IFile)res)) {
1190                                                                 return true;
1191                                                         }
1192                                                 }
1193                                         } else {
1194                                                 return true;
1195                                         }
1196                                 }
1197                         }
1198                 }
1199                 return false;
1200         }
1201
1202         /**
1203          * Generic processing for elements with changed contents:<ul>
1204          * <li>The element is closed such that any subsequent accesses will re-open
1205          * the element reflecting its new structure.
1206          * <li>An entry is made in the delta reporting a content change (K_CHANGE with F_CONTENT flag set).
1207          * </ul>
1208          */
1209 //      protected void nonJavaResourcesChanged(Openable element, IResourceDelta delta)
1210 //              throws JavaModelException {
1211 //
1212 //              // reset non-java resources if element was open
1213 //              if (element.isOpen()) {
1214 //                      JavaElementInfo info = (JavaElementInfo)element.getElementInfo();
1215 //                      switch (element.getElementType()) {
1216 //                              case IJavaElement.JAVA_MODEL :
1217 //                                      ((JavaModelInfo) info).nonJavaResources = null;
1218 //                                      currentDelta().addResourceDelta(delta);
1219 //                                      return;
1220 //                              case IJavaElement.JAVA_PROJECT :
1221 //                                      ((JavaProjectElementInfo) info).setNonJavaResources(null);
1222 //      
1223 //                                      // if a package fragment root is the project, clear it too
1224 //                                      JavaProject project = (JavaProject) element;
1225 //                                      PackageFragmentRoot projectRoot =
1226 //                                              (PackageFragmentRoot) project.getPackageFragmentRoot(project.getProject());
1227 //                                      if (projectRoot.isOpen()) {
1228 //                                              ((PackageFragmentRootInfo) projectRoot.getElementInfo()).setNonJavaResources(
1229 //                                                      null);
1230 //                                      }
1231 //                                      break;
1232 //                              case IJavaElement.PACKAGE_FRAGMENT :
1233 //                                       ((PackageFragmentInfo) info).setNonJavaResources(null);
1234 //                                      break;
1235 //                              case IJavaElement.PACKAGE_FRAGMENT_ROOT :
1236 //                                       ((PackageFragmentRootInfo) info).setNonJavaResources(null);
1237 //                      }
1238 //              }
1239 //
1240 //              JavaElementDelta elementDelta = currentDelta().find(element);
1241 //              if (elementDelta == null) {
1242 //                      currentDelta().changed(element, IJavaElementDelta.F_CONTENT);
1243 //                      elementDelta = currentDelta().find(element);
1244 //              }
1245 //              elementDelta.addResourceDelta(delta);
1246 //      }
1247 //      private OutputsInfo outputsInfo(RootInfo rootInfo, IResource res) {
1248 //              try {
1249 //                      IJavaProject proj =
1250 //                              rootInfo == null ?
1251 //                                      (IJavaProject)this.createElement(res.getProject(), IJavaElement.JAVA_PROJECT, null) :
1252 //                                      rootInfo.project;
1253 //                      if (proj != null) {
1254 //                              IPath projectOutput = proj.getOutputLocation();
1255 //                              int traverseMode = IGNORE;
1256 //                              if (proj.getProject().getFullPath().equals(projectOutput)){ // case of proj==bin==src
1257 //                                      return new OutputsInfo(new IPath[] {projectOutput}, new int[] {SOURCE}, 1);
1258 //                              } else {
1259 //                                      IClasspathEntry[] classpath = proj.getResolvedClasspath(true);
1260 //                                      IPath[] outputs = new IPath[classpath.length+1];
1261 //                                      int[] traverseModes = new int[classpath.length+1];
1262 //                                      int outputCount = 1;
1263 //                                      outputs[0] = projectOutput;
1264 //                                      traverseModes[0] = traverseMode;
1265 //                                      for (int i = 0, length = classpath.length; i < length; i++) {
1266 //                                              IClasspathEntry entry = classpath[i];
1267 //                                              IPath entryPath = entry.getPath();
1268 //                                              IPath output = entry.getOutputLocation();
1269 //                                              if (output != null) {
1270 //                                                      outputs[outputCount] = output;
1271 //                                                      // check case of src==bin
1272 //                                                      if (entryPath.equals(output)) {
1273 //                                                              traverseModes[outputCount++] = (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) ? SOURCE : BINARY;
1274 //                                                      } else {
1275 //                                                              traverseModes[outputCount++] = IGNORE;
1276 //                                                      }
1277 //                                              }
1278 //                                              
1279 //                                              // check case of src==bin
1280 //                                              if (entryPath.equals(projectOutput)) {
1281 //                                                      traverseModes[0] = (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) ? SOURCE : BINARY;
1282 //                                              }
1283 //                                      }
1284 //                                      return new OutputsInfo(outputs, traverseModes, outputCount);
1285 //                              }
1286 //                      }
1287 //              } catch (JavaModelException e) {
1288 //              }
1289 //              return null;
1290 //      }
1291         
1292         /**
1293          * Check whether the updated file is affecting some of the properties of a given project (like
1294          * its classpath persisted as a file).
1295          * Also force classpath problems to be refresh if not running in autobuild mode.
1296          * NOTE: It can induce resource changes, and cannot be called during POST_CHANGE notification.
1297          *
1298          */
1299 //      public void performPreBuildCheck(
1300 //              IResourceDelta delta,
1301 //              IJavaElement parent) {
1302 //      
1303 //              IResource resource = delta.getResource();
1304 //              IJavaElement element = null;
1305 //              boolean processChildren = false;
1306 //      
1307 //              switch (resource.getType()) {
1308 //      
1309 //                      case IResource.ROOT :
1310 //                              if (delta.getKind() == IResourceDelta.CHANGED) {
1311 //                                      element = JavaCore.create(resource);
1312 //                                      processChildren = true;
1313 //                              }
1314 //                              break;
1315 //                      case IResource.PROJECT :
1316 //                              int kind = delta.getKind();
1317 //                              switch (kind) {
1318 //                                      case IResourceDelta.CHANGED:
1319 //                                              // do not visit non-java projects (see bug 16140 Non-java project gets .classpath)
1320 //                                              IProject project = (IProject)resource;
1321 //                                              if (JavaProject.hasJavaNature(project)) {
1322 //                                                      element = JavaCore.create(resource);
1323 //                                                      processChildren = true;
1324 //                                              } else if (JavaModelManager.getJavaModelManager().getJavaModel().findJavaProject(project) != null) {
1325 //                                                      // project had the java nature
1326 //                                                      this.rootsAreStale = true;
1327 //
1328 //                                                      // remove classpath cache so that initializeRoots() will not consider the project has a classpath
1329 //                                                      this.manager.removePerProjectInfo((JavaProject)JavaCore.create(project));
1330 //                                              }
1331 //                                              break;
1332 //                                      case IResourceDelta.ADDED:
1333 //                                              this.rootsAreStale = true;
1334 //                                              break;
1335 //                                      case IResourceDelta.REMOVED:
1336 //                                              // remove classpath cache so that initializeRoots() will not consider the project has a classpath
1337 //                                              this.manager.removePerProjectInfo((JavaProject)JavaCore.create(resource));
1338 //                                              
1339 //                                              this.rootsAreStale = true;
1340 //                                              break;
1341 //                              }
1342 //                              break;
1343 //                      case IResource.FILE :
1344 //                              if (parent.getElementType() == IJavaElement.JAVA_PROJECT) {
1345 //                                      IFile file = (IFile) resource;
1346 //                                      JavaProject project = (JavaProject) parent;
1347 //      
1348 //                                      /* check classpath file change */
1349 //                                      if (file.getName().equals(JavaProject.CLASSPATH_FILENAME)) {
1350 //                                              reconcileClasspathFileUpdate(delta, file, project);
1351 //                                              this.rootsAreStale = true;
1352 //                                              break;
1353 //                                      }
1354 ////                                    /* check custom preference file change */
1355 ////                                    if (file.getName().equals(JavaProject.PREF_FILENAME)) {
1356 ////                                            reconcilePreferenceFileUpdate(delta, file, project);
1357 ////                                            break;
1358 ////                                    }
1359 //                              }
1360 //                              break;
1361 //              }
1362 //              if (processChildren) {
1363 //                      IResourceDelta[] children = delta.getAffectedChildren();
1364 //                      for (int i = 0; i < children.length; i++) {
1365 //                              performPreBuildCheck(children[i], element);
1366 //                      }
1367 //              }
1368 //      }
1369         
1370 //      private void popUntilPrefixOf(IPath path) {
1371 //              while (this.currentElement != null) {
1372 //                      IPath currentElementPath = null;
1373 //                      if (this.currentElement instanceof IPackageFragmentRoot) {
1374 //                              currentElementPath = ((IPackageFragmentRoot)this.currentElement).getPath();
1375 //                      } else {
1376 //                              IResource currentElementResource = this.currentElement.getResource();
1377 //                              if (currentElementResource != null) {
1378 //                                      currentElementPath = currentElementResource.getFullPath();
1379 //                              }
1380 //                      }
1381 //                      if (currentElementPath != null) {
1382 //                              if (this.currentElement instanceof IPackageFragment 
1383 //                                      && this.currentElement.getElementName().length() == 0
1384 //                                      && currentElementPath.segmentCount() != path.segmentCount()-1) {
1385 //                                              // default package and path is not a direct child
1386 //                                              this.currentElement = (Openable)this.currentElement.getParent();
1387 //                              }
1388 //                              if (currentElementPath.isPrefixOf(path)) {
1389 //                                      return;
1390 //                              }
1391 //                      }
1392 //                      this.currentElement = (Openable)this.currentElement.getParent();
1393 //              }
1394 //      }
1395
1396         /**
1397          * Converts a <code>IResourceDelta</code> rooted in a <code>Workspace</code> into
1398          * the corresponding set of <code>IJavaElementDelta</code>, rooted in the
1399          * relevant <code>JavaModel</code>s.
1400          */
1401 //      public IJavaElementDelta processResourceDelta(IResourceDelta changes) {
1402 //
1403 //              try {
1404 //                      IJavaModel model = this.manager.getJavaModel();
1405 //                      if (!model.isOpen()) {
1406 //                              // force opening of java model so that java element delta are reported
1407 //                              try {
1408 //                                      model.open(null);
1409 //                              } catch (JavaModelException e) {
1410 //                                      if (VERBOSE) {
1411 //                                              e.printStackTrace();
1412 //                                      }
1413 //                                      return null;
1414 //                              }
1415 //                      }
1416 //                      this.initializeRoots();
1417 //                      this.currentElement = null;
1418 //                      
1419 //                      // get the workspace delta, and start processing there.
1420 //                      IResourceDelta[] deltas = changes.getAffectedChildren();
1421 //                      for (int i = 0; i < deltas.length; i++) {
1422 //                              IResourceDelta delta = deltas[i];
1423 //                              IResource res = delta.getResource();
1424 //                              
1425 //                              // find out the element type
1426 //                              RootInfo rootInfo = null;
1427 //                              int elementType;
1428 //                              IProject proj = (IProject)res;
1429 //                              boolean wasJavaProject = this.manager.getJavaModel().findJavaProject(proj) != null;
1430 //                              boolean isJavaProject = JavaProject.hasJavaNature(proj);
1431 //                              if (!wasJavaProject && !isJavaProject) {
1432 //                                      elementType = NON_JAVA_RESOURCE;
1433 //                              } else {
1434 //                                      rootInfo = this.enclosingRootInfo(res.getFullPath(), delta.getKind());
1435 //                                      if (rootInfo != null && rootInfo.isRootOfProject(res.getFullPath())) {
1436 //                                              elementType = IJavaElement.PACKAGE_FRAGMENT_ROOT;
1437 //                                      } else {
1438 //                                              elementType = IJavaElement.JAVA_PROJECT; 
1439 //                                      }
1440 //                              }
1441 //                              
1442 //                              // traverse delta
1443 //                              if (!this.traverseDelta(delta, elementType, rootInfo, null) 
1444 //                                              || (wasJavaProject != isJavaProject && (delta.getKind()) == IResourceDelta.CHANGED)) { // project has changed nature (description or open/closed)
1445 //                                      try {
1446 //                                              // add child as non java resource
1447 //                                              nonJavaResourcesChanged((JavaModel)model, delta);
1448 //                                      } catch (JavaModelException e) {
1449 //                                      }
1450 //                              }
1451 //
1452 //                      }
1453 //                      
1454 //                      // update package fragment roots of projects that were affected
1455 //                      Iterator iterator = this.projectsToUpdate.iterator();
1456 //                      while (iterator.hasNext()) {
1457 //                              JavaProject project = (JavaProject)iterator.next();
1458 //                              project.updatePackageFragmentRoots();
1459 //                      }
1460 //      
1461 //                      updateDependentNamelookups();
1462 //
1463 //                      return this.currentDelta;
1464 //              } finally {
1465 //                      this.currentDelta = null;
1466 //                      this.projectsToUpdate.clear();
1467 //                      this.projectsForDependentNamelookupRefresh.clear();
1468 //              }
1469 //      }
1470
1471         /**
1472          * Update the JavaModel according to a .classpath file change. The file can have changed as a result of a previous
1473          * call to JavaProject#setRawClasspath or as a result of some user update (through repository)
1474          */
1475 //      void reconcileClasspathFileUpdate(IResourceDelta delta, IFile file, JavaProject project) {
1476 //                      
1477 //              switch (delta.getKind()) {
1478 //                      case IResourceDelta.REMOVED : // recreate one based on in-memory classpath
1479 //                              try {
1480 //                                      JavaModelManager.PerProjectInfo info = JavaModelManager.getJavaModelManager().getPerProjectInfoCheckExistence(project.getProject());
1481 //                                      if (info.classpath != null) { // if there is an in-memory classpath
1482 //                                              project.saveClasspath(info.classpath, info.outputLocation);
1483 //                                      }
1484 //                              } catch (JavaModelException e) {
1485 //                                      if (project.getProject().isAccessible()) {
1486 //                                              Util.log(e, "Could not save classpath for "+ project.getPath()); //$NON-NLS-1$
1487 //                                      }
1488 //                              }
1489 //                              break;
1490 //                      case IResourceDelta.CHANGED :
1491 //                              if ((delta.getFlags() & IResourceDelta.CONTENT) == 0  // only consider content change
1492 //                                              && (delta.getFlags() & IResourceDelta.MOVED_FROM) == 0) // and also move and overide scenario (see http://dev.eclipse.org/bugs/show_bug.cgi?id=21420)
1493 //                                      break;
1494 //                      case IResourceDelta.ADDED :
1495 //                              // check if any actual difference
1496 //                              project.flushClasspathProblemMarkers(false, true);
1497 //                              boolean wasSuccessful = false; // flag recording if .classpath file change got reflected
1498 //                              try {
1499 //                                      // force to (re)read the property file
1500 //                                      IClasspathEntry[] fileEntries = project.readClasspathFile(true/*create markers*/, false/*don't log problems*/);
1501 //                                      if (fileEntries == null)
1502 //                                              break; // could not read, ignore 
1503 //                                      JavaModelManager.PerProjectInfo info = JavaModelManager.getJavaModelManager().getPerProjectInfoCheckExistence(project.getProject());
1504 //                                      if (info.classpath != null) { // if there is an in-memory classpath
1505 //                                              if (project.isClasspathEqualsTo(info.classpath, info.outputLocation, fileEntries)) {
1506 //                                                      wasSuccessful = true;
1507 //                                                      break;
1508 //                                              }
1509 //                                      }
1510 //              
1511 //                                      // will force an update of the classpath/output location based on the file information
1512 //                                      // extract out the output location
1513 //                                      IPath outputLocation = null;
1514 //                                      if (fileEntries != null && fileEntries.length > 0) {
1515 //                                              IClasspathEntry entry = fileEntries[fileEntries.length - 1];
1516 //                                              if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) {
1517 //                                                      outputLocation = entry.getPath();
1518 //                                                      IClasspathEntry[] copy = new IClasspathEntry[fileEntries.length - 1];
1519 //                                                      System.arraycopy(fileEntries, 0, copy, 0, copy.length);
1520 //                                                      fileEntries = copy;
1521 //                                              }
1522 //                                      }
1523 //                                      // restore output location                              
1524 //                                      if (outputLocation == null) {
1525 //                                              outputLocation = SetClasspathOperation.ReuseOutputLocation;
1526 //                                              // clean mode will also default to reusing current one
1527 //                                      }
1528 //                                      project.setRawClasspath(
1529 //                                              fileEntries, 
1530 //                                              outputLocation, 
1531 //                                              null, // monitor
1532 //                                              true, // canChangeResource
1533 //                                              project.getResolvedClasspath(true), // ignoreUnresolvedVariable
1534 //                                              true, // needValidation
1535 //                                              false); // no need to save
1536 //                                      
1537 //                                      // if reach that far, the classpath file change got absorbed
1538 //                                      wasSuccessful = true;
1539 //                              } catch (RuntimeException e) {
1540 //                                      // setRawClasspath might fire a delta, and a listener may throw an exception
1541 //                                      if (project.getProject().isAccessible()) {
1542 //                                              Util.log(e, "Could not set classpath for "+ project.getPath()); //$NON-NLS-1$
1543 //                                      }
1544 //                                      break;
1545 //                              } catch (JavaModelException e) { // CP failed validation
1546 //                                      if (project.getProject().isAccessible()) {
1547 //                                              if (e.getJavaModelStatus().getException() instanceof CoreException) {
1548 //                                                      // happens if the .classpath could not be written to disk
1549 //                                                      project.createClasspathProblemMarker(new JavaModelStatus(
1550 //                                                                      IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
1551 //                                                                      Util.bind("classpath.couldNotWriteClasspathFile", project.getElementName(), e.getMessage()))); //$NON-NLS-1$
1552 //                                              } else {
1553 //                                                      project.createClasspathProblemMarker(new JavaModelStatus(
1554 //                                                                      IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
1555 //                                                                      Util.bind("classpath.invalidClasspathInClasspathFile", project.getElementName(), e.getMessage()))); //$NON-NLS-1$
1556 //                                              }                       
1557 //                                      }
1558 //                                      break;
1559 //                              } finally {
1560 //                                      if (!wasSuccessful) { 
1561 //                                              try {
1562 //                                                      project.setRawClasspath0(JavaProject.INVALID_CLASSPATH);
1563 //                                                      project.updatePackageFragmentRoots();
1564 //                                              } catch (JavaModelException e) {
1565 //                                              }
1566 //                                      }
1567 //                              }
1568 //              }
1569 //      }
1570
1571         /**
1572          * Update the JavaModel according to a .jprefs file change. The file can have changed as a result of a previous
1573          * call to JavaProject#setOptions or as a result of some user update (through repository)
1574          * Unused until preference file get shared (.jpref)
1575          */
1576 //      void reconcilePreferenceFileUpdate(IResourceDelta delta, IFile file, JavaProject project) {
1577 //                      
1578 //              switch (delta.getKind()) {
1579 //                      case IResourceDelta.REMOVED : // flush project custom settings
1580 //                              project.setOptions(null);
1581 //                              return;
1582 //                      case IResourceDelta.CHANGED :
1583 //                              if ((delta.getFlags() & IResourceDelta.CONTENT) == 0  // only consider content change
1584 //                                              && (delta.getFlags() & IResourceDelta.MOVED_FROM) == 0) // and also move and overide scenario
1585 //                                      break;
1586 //                              identityCheck : { // check if any actual difference
1587 //                                      // force to (re)read the property file
1588 //                                      Preferences filePreferences = project.loadPreferences();
1589 //                                      if (filePreferences == null){ 
1590 //                                              project.setOptions(null); // should have got removed delta.
1591 //                                              return;
1592 //                                      }
1593 //                                      Preferences projectPreferences = project.getPreferences();
1594 //                                      if (projectPreferences == null) return; // not a Java project
1595 //                                              
1596 //                                      // compare preferences set to their default
1597 //                                      String[] defaultProjectPropertyNames = projectPreferences.defaultPropertyNames();
1598 //                                      String[] defaultFilePropertyNames = filePreferences.defaultPropertyNames();
1599 //                                      if (defaultProjectPropertyNames.length == defaultFilePropertyNames.length) {
1600 //                                              for (int i = 0; i < defaultProjectPropertyNames.length; i++){
1601 //                                                      String propertyName = defaultProjectPropertyNames[i];
1602 //                                                      if (!projectPreferences.getString(propertyName).trim().equals(filePreferences.getString(propertyName).trim())){
1603 //                                                              break identityCheck;
1604 //                                                      }
1605 //                                              }               
1606 //                                      } else break identityCheck;
1607 //
1608 //                                      // compare custom preferences not set to their default
1609 //                                      String[] projectPropertyNames = projectPreferences.propertyNames();
1610 //                                      String[] filePropertyNames = filePreferences.propertyNames();
1611 //                                      if (projectPropertyNames.length == filePropertyNames.length) {
1612 //                                              for (int i = 0; i < projectPropertyNames.length; i++){
1613 //                                              String propertyName = projectPropertyNames[i];
1614 //                                                      if (!projectPreferences.getString(propertyName).trim().equals(filePreferences.getString(propertyName).trim())){
1615 //                                                              break identityCheck;
1616 //                                                      }
1617 //                                              }               
1618 //                                      } else break identityCheck;
1619 //                                      
1620 //                                      // identical - do nothing
1621 //                                      return;
1622 //                              }
1623 //                      case IResourceDelta.ADDED :
1624 //                              // not identical, create delta and reset cached preferences
1625 //                              project.setPreferences(null);
1626 //                              // create delta
1627 //                              //fCurrentDelta.changed(project, IJavaElementDelta.F_OPTIONS_CHANGED);                          
1628 //              }
1629 //      }
1630
1631         /**
1632          * Removes the given element from its parents cache of children. If the
1633          * element does not have a parent, or the parent is not currently open,
1634          * this has no effect. 
1635          */
1636         protected void removeFromParentInfo(Openable child) {
1637
1638                 Openable parent = (Openable) child.getParent();
1639                 if (parent != null && parent.isOpen()) {
1640                         try {
1641                                 JavaElementInfo info = (JavaElementInfo)parent.getElementInfo();
1642                                 info.removeChild(child);
1643                         } catch (JavaModelException e) {
1644                                 // do nothing - we already checked if open
1645                         }
1646                 }
1647         }
1648         /**
1649          * Notification that some resource changes have happened
1650          * on the platform, and that the Java Model should update any required
1651          * internal structures such that its elements remain consistent.
1652          * Translates <code>IResourceDeltas</code> into <code>IJavaElementDeltas</code>.
1653          *
1654          * @see IResourceDelta
1655          * @see IResource 
1656          */
1657         public void resourceChanged(IResourceChangeEvent event) {
1658         
1659                 if (event.getSource() instanceof IWorkspace) {
1660                         IResource resource = event.getResource();
1661                         IResourceDelta delta = event.getDelta();
1662                         
1663                         switch(event.getType()){
1664                                 case IResourceChangeEvent.PRE_DELETE :
1665                                         try {
1666                                                 if(resource.getType() == IResource.PROJECT 
1667                                                         && ((IProject) resource).hasNature(JavaCore.NATURE_ID)) {
1668                                                 // TODO khartlage temp-del
1669 //                                                      this.deleting((IProject)resource);
1670                                                 }
1671                                         } catch(CoreException e){
1672                                         }
1673                                         return;
1674                                         
1675                                 case IResourceChangeEvent.PRE_AUTO_BUILD :
1676 //                      TODO khartlage temp-del
1677 //                                      if(isAffectedBy(delta)) { // avoid populating for SYNC or MARKER deltas
1678 //                                              this.checkProjectsBeingAddedOrRemoved(delta);
1679 //                                              
1680 //                                              // update the classpath related markers
1681 //                                              this.updateClasspathMarkers();
1682 //      
1683 //                                              // the following will close project if affected by the property file change
1684 //                                              try {
1685 //                                                      // don't fire classpath change deltas right away, but batch them
1686 //                                                      this.manager.stopDeltas();
1687 //                                                      this.performPreBuildCheck(delta, null); 
1688 //                                              } finally {
1689 //                                                      this.manager.startDeltas();
1690 //                                              }
1691 //                                      }
1692                                         // only fire already computed deltas (resource ones will be processed in post change only)
1693                                         this.manager.fire(null, ElementChangedEvent.PRE_AUTO_BUILD);
1694                                         break;
1695
1696                                 case IResourceChangeEvent.POST_AUTO_BUILD :
1697 //                      TODO khartlage temp-del
1698 //                                      JavaBuilder.finishedBuilding(event);
1699                                         break;
1700                                         
1701                                 case IResourceChangeEvent.POST_CHANGE :
1702 //                      TODO khartlage temp-del
1703 //                                      if (isAffectedBy(delta)) {
1704 //                                              try {
1705 //                                                      if (this.refreshedElements != null) {
1706 //                                                              try {
1707 //                                                                      createExternalArchiveDelta(null);
1708 //                                                              } catch (JavaModelException e) {
1709 //                                                                      e.printStackTrace();
1710 //                                                              }
1711 //                                                      }
1712 //                                                      IJavaElementDelta translatedDelta = this.processResourceDelta(delta);
1713 //                                                      if (translatedDelta != null) { 
1714 //                                                              this.manager.registerJavaModelDelta(translatedDelta);
1715 //                                                      }
1716 //                                                      this.manager.fire(null, ElementChangedEvent.POST_CHANGE);
1717 //                                              } finally {
1718 //                                                      // workaround for bug 15168 circular errors not reported 
1719 //                                                      this.manager.javaProjectsCache = null;
1720 //                                                      this.removedRoots = null;
1721 //                                              }
1722 //                                      }
1723                         }
1724                 }
1725         }
1726         /*
1727          * Finds the root info this path is included in.
1728          * Returns null if not found.
1729          */
1730         RootInfo enclosingRootInfo(IPath path, int kind) {
1731                 while (path != null && path.segmentCount() > 0) {
1732                         RootInfo rootInfo =  this.rootInfo(path, kind);
1733                         if (rootInfo != null) return rootInfo;
1734                         path = path.removeLastSegments(1);
1735                 }
1736                 return null;
1737         }
1738         /*
1739          * Returns the root info for the given path. Look in the old roots table if kind is REMOVED.
1740          */
1741         RootInfo rootInfo(IPath path, int kind) {
1742                 if (kind == IResourceDelta.REMOVED) {
1743                         return (RootInfo)this.oldRoots.get(path);
1744                 } else {
1745                         return (RootInfo)this.roots.get(path);
1746                 }
1747         }
1748         /*
1749          * Returns the other root infos for the given path. Look in the old other roots table if kind is REMOVED.
1750          */
1751         ArrayList otherRootsInfo(IPath path, int kind) {
1752                 if (kind == IResourceDelta.REMOVED) {
1753                         return (ArrayList)this.oldOtherRoots.get(path);
1754                 } else {
1755                         return (ArrayList)this.otherRoots.get(path);
1756                 }
1757         }       
1758
1759         /**
1760          * Converts an <code>IResourceDelta</code> and its children into
1761          * the corresponding <code>IJavaElementDelta</code>s.
1762          * Return whether the delta corresponds to a java element.
1763          * If it is not a java element, it will be added as a non-java
1764          * resource by the sender of this method.
1765          */
1766 //      protected boolean traverseDelta(
1767 //              IResourceDelta delta, 
1768 //              int elementType, 
1769 //              RootInfo rootInfo,
1770 //              OutputsInfo outputsInfo) {
1771 //                      
1772 //              IResource res = delta.getResource();
1773 //      
1774 //              // set stack of elements
1775 //              if (this.currentElement == null && rootInfo != null) {
1776 //                      this.currentElement = (Openable)rootInfo.project;
1777 //              }
1778 //              
1779 //              // process current delta
1780 //              boolean processChildren = true;
1781 //              if (res instanceof IProject) {
1782 //                      processChildren = 
1783 //                              this.updateCurrentDeltaAndIndex(
1784 //                                      delta, 
1785 //                                      elementType == IJavaElement.PACKAGE_FRAGMENT_ROOT ? 
1786 //                                              IJavaElement.JAVA_PROJECT : // case of prj=src
1787 //                                              elementType, 
1788 //                                      rootInfo);
1789 //              } else if (rootInfo != null) {
1790 //                      processChildren = this.updateCurrentDeltaAndIndex(delta, elementType, rootInfo);
1791 //              } else {
1792 //                      // not yet inside a package fragment root
1793 //                      processChildren = true;
1794 //              }
1795 //              
1796 //              // get the project's output locations and traverse mode
1797 //              if (outputsInfo == null) outputsInfo = this.outputsInfo(rootInfo, res);
1798 //      
1799 //              // process children if needed
1800 //              if (processChildren) {
1801 //                      IResourceDelta[] children = delta.getAffectedChildren();
1802 //                      boolean oneChildOnClasspath = false;
1803 //                      int length = children.length;
1804 //                      IResourceDelta[] orphanChildren = null;
1805 //                      Openable parent = null;
1806 //                      boolean isValidParent = true;
1807 //                      for (int i = 0; i < length; i++) {
1808 //                              IResourceDelta child = children[i];
1809 //                              IResource childRes = child.getResource();
1810 //      
1811 //                              // check source attachment change
1812 //                              this.checkSourceAttachmentChange(child, childRes);
1813 //                              
1814 //                              // find out whether the child is a package fragment root of the current project
1815 //                              IPath childPath = childRes.getFullPath();
1816 //                              int childKind = child.getKind();
1817 //                              RootInfo childRootInfo = this.rootInfo(childPath, childKind);
1818 //                              if (childRootInfo != null && !childRootInfo.isRootOfProject(childPath)) {
1819 //                                      // package fragment root of another project (dealt with later)
1820 //                                      childRootInfo = null;
1821 //                              }
1822 //                              
1823 //                              // compute child type
1824 //                              int childType = 
1825 //                                      this.elementType(
1826 //                                              childRes, 
1827 //                                              childKind,
1828 //                                              elementType, 
1829 //                                              rootInfo == null ? childRootInfo : rootInfo
1830 //                                      );
1831 //                                              
1832 //                              // is childRes in the output folder and is it filtered out ?
1833 //                              boolean isResFilteredFromOutput = this.isResFilteredFromOutput(outputsInfo, childRes, childType);
1834 //
1835 //                              boolean isNestedRoot = rootInfo != null && childRootInfo != null;
1836 //                              if (!isResFilteredFromOutput 
1837 //                                              && !isNestedRoot) { // do not treat as non-java rsc if nested root
1838 //                                      if (!this.traverseDelta(child, childType, rootInfo == null ? childRootInfo : rootInfo, outputsInfo)) { // traverse delta for child in the same project
1839 //                                              // it is a non-java resource
1840 //                                              try {
1841 //                                                      if (rootInfo != null) { // if inside a package fragment root
1842 //                                                              if (!isValidParent) continue; 
1843 //                                                              if (parent == null) {
1844 //                                                                      // find the parent of the non-java resource to attach to
1845 //                                                                      if (this.currentElement == null 
1846 //                                                                                      || !this.currentElement.getJavaProject().equals(rootInfo.project)) {
1847 //                                                                              // force the currentProject to be used
1848 //                                                                              this.currentElement = (Openable)rootInfo.project;
1849 //                                                                      }
1850 //                                                                      if (elementType == IJavaElement.JAVA_PROJECT
1851 //                                                                              || (elementType == IJavaElement.PACKAGE_FRAGMENT_ROOT 
1852 //                                                                                      && res instanceof IProject)) { 
1853 //                                                                              // NB: attach non-java resource to project (not to its package fragment root)
1854 //                                                                              parent = (Openable)rootInfo.project;
1855 //                                                                      } else {
1856 //                                                                              parent = this.createElement(res, elementType, rootInfo);
1857 //                                                                      }
1858 //                                                                      if (parent == null) {
1859 //                                                                              isValidParent = false;
1860 //                                                                              continue;
1861 //                                                                      }
1862 //                                                              }
1863 //                                                              // add child as non java resource
1864 //                                                              nonJavaResourcesChanged(parent, child);
1865 //                                                      } else {
1866 //                                                              // the non-java resource (or its parent folder) will be attached to the java project
1867 //                                                              if (orphanChildren == null) orphanChildren = new IResourceDelta[length];
1868 //                                                              orphanChildren[i] = child;
1869 //                                                      }
1870 //                                              } catch (JavaModelException e) {
1871 //                                              }
1872 //                                      } else {
1873 //                                              oneChildOnClasspath = true;
1874 //                                      }
1875 //                              } else {
1876 //                                      oneChildOnClasspath = true; // to avoid reporting child delta as non-java resource delta
1877 //                              }
1878 //                                                              
1879 //                              // if child is a nested root 
1880 //                              // or if it is not a package fragment root of the current project
1881 //                              // but it is a package fragment root of another project, traverse delta too
1882 //                              if (isNestedRoot 
1883 //                                              || (childRootInfo == null && (childRootInfo = this.rootInfo(childPath, childKind)) != null)) {
1884 //                                      this.traverseDelta(child, IJavaElement.PACKAGE_FRAGMENT_ROOT, childRootInfo, null); // binary output of childRootInfo.project cannot be this root
1885 //                                      // NB: No need to check the return value as the child can only be on the classpath
1886 //                              }
1887 //      
1888 //                              // if the child is a package fragment root of one or several other projects
1889 //                              ArrayList rootList;
1890 //                              if ((rootList = this.otherRootsInfo(childPath, childKind)) != null) {
1891 //                                      Iterator iterator = rootList.iterator();
1892 //                                      while (iterator.hasNext()) {
1893 //                                              childRootInfo = (RootInfo) iterator.next();
1894 //                                              this.traverseDelta(child, IJavaElement.PACKAGE_FRAGMENT_ROOT, childRootInfo, null); // binary output of childRootInfo.project cannot be this root
1895 //                                      }
1896 //                              }
1897 //                      }
1898 //                      if (orphanChildren != null
1899 //                                      && (oneChildOnClasspath // orphan children are siblings of a package fragment root
1900 //                                              || res instanceof IProject)) { // non-java resource directly under a project
1901 //                                              
1902 //                              // attach orphan children
1903 //                              IProject rscProject = res.getProject();
1904 //                              JavaProject adoptiveProject = (JavaProject)JavaCore.create(rscProject);
1905 //                              if (adoptiveProject != null 
1906 //                                              && JavaProject.hasJavaNature(rscProject)) { // delta iff Java project (18698)
1907 //                                      for (int i = 0; i < length; i++) {
1908 //                                              if (orphanChildren[i] != null) {
1909 //                                                      try {
1910 //                                                              nonJavaResourcesChanged(adoptiveProject, orphanChildren[i]);
1911 //                                                      } catch (JavaModelException e) {
1912 //                                                      }
1913 //                                              }
1914 //                                      }
1915 //                              }
1916 //                      } // else resource delta will be added by parent
1917 //                      return elementType != NON_JAVA_RESOURCE; // TODO: (jerome) do we still need to return? (check could be done by caller)
1918 //              } else {
1919 //                      return elementType != NON_JAVA_RESOURCE;
1920 //              }
1921 //      }
1922
1923         /**
1924          * Update the classpath markers and cycle markers for the projects to update.
1925          */
1926 //      void updateClasspathMarkers() {
1927 //              try {
1928 //                      if (!ResourcesPlugin.getWorkspace().isAutoBuilding()) {
1929 //                              Iterator iterator = this.projectsToUpdate.iterator();
1930 //                              while (iterator.hasNext()) {
1931 //                                      try {
1932 //                                              JavaProject project = (JavaProject)iterator.next();
1933 //                                              
1934 //                                               // force classpath marker refresh
1935 //                                              project.getResolvedClasspath(
1936 //                                                      true, // ignoreUnresolvedEntry
1937 //                                                      true); // generateMarkerOnError
1938 //                                              
1939 //                                      } catch (JavaModelException e) {
1940 //                                      }
1941 //                              }
1942 //                      }
1943 //                      if (!this.projectsToUpdate.isEmpty()){
1944 //                              try {
1945 //                                      // update all cycle markers
1946 //                                      JavaProject.updateAllCycleMarkers();
1947 //                              } catch (JavaModelException e) {
1948 //                              }
1949 //                      }                               
1950 //              } finally {
1951 //                      this.projectsToUpdate = new HashSet();
1952 //              }
1953 //      }
1954
1955         /*
1956          * Update the current delta (ie. add/remove/change the given element) and update the correponding index.
1957          * Returns whether the children of the given delta must be processed.
1958          * @throws a JavaModelException if the delta doesn't correspond to a java element of the given type.
1959          */
1960 //      private boolean updateCurrentDeltaAndIndex(IResourceDelta delta, int elementType, RootInfo rootInfo) {
1961 //              Openable element;
1962 //              switch (delta.getKind()) {
1963 //                      case IResourceDelta.ADDED :
1964 //                              IResource deltaRes = delta.getResource();
1965 //                              element = this.createElement(deltaRes, elementType, rootInfo);
1966 //                              if (element == null) {
1967 //                                      // resource might be containing shared roots (see bug 19058)
1968 //                                      this.updateRoots(deltaRes.getFullPath(), delta);
1969 //                                      return false;
1970 //                              }
1971 //                              this.updateIndex(element, delta);
1972 //                              this.elementAdded(element, delta, rootInfo);
1973 //                              return false;
1974 //                      case IResourceDelta.REMOVED :
1975 //                              deltaRes = delta.getResource();
1976 //                              element = this.createElement(deltaRes, elementType, rootInfo);
1977 //                              if (element == null) {
1978 //                                      // resource might be containing shared roots (see bug 19058)
1979 //                                      this.updateRoots(deltaRes.getFullPath(), delta);
1980 //                                      return false;
1981 //                              }
1982 //                              this.updateIndex(element, delta);
1983 //                              this.elementRemoved(element, delta, rootInfo);
1984 //      
1985 //                              if (deltaRes.getType() == IResource.PROJECT){                   
1986 //                                      // reset the corresponding project built state, since cannot reuse if added back
1987 //                                      this.manager.setLastBuiltState((IProject)deltaRes, null /*no state*/);
1988 //                              }
1989 //                              return false;
1990 //                      case IResourceDelta.CHANGED :
1991 //                              int flags = delta.getFlags();
1992 //                              if ((flags & IResourceDelta.CONTENT) != 0) {
1993 //                                      // content has changed
1994 //                                      element = this.createElement(delta.getResource(), elementType, rootInfo);
1995 //                                      if (element == null) return false;
1996 //                                      this.updateIndex(element, delta);
1997 //                                      this.contentChanged(element, delta);
1998 //                              } else if (elementType == IJavaElement.JAVA_PROJECT) {
1999 //                                      if ((flags & IResourceDelta.OPEN) != 0) {
2000 //                                              // project has been opened or closed
2001 //                                              IProject res = (IProject)delta.getResource();
2002 //                                              element = this.createElement(res, elementType, rootInfo);
2003 //                                              if (element == null) {
2004 //                                                      // resource might be containing shared roots (see bug 19058)
2005 //                                                      this.updateRoots(res.getFullPath(), delta);
2006 //                                                      return false;
2007 //                                              }
2008 //                                              if (res.isOpen()) {
2009 //                                                      if (JavaProject.hasJavaNature(res)) {
2010 //                                                              this.elementAdded(element, delta, rootInfo);
2011 //                                                              this.indexManager.indexAll(res);
2012 //                                                      }
2013 //                                              } else {
2014 //                                                      JavaModel javaModel = this.manager.getJavaModel();
2015 //                                                      boolean wasJavaProject = javaModel.findJavaProject(res) != null;
2016 //                                                      if (wasJavaProject) {
2017 //                                                              this.elementRemoved(element, delta, rootInfo);
2018 //                                                              this.indexManager.discardJobs(element.getElementName());
2019 //                                                              this.indexManager.removeIndexFamily(res.getFullPath());
2020 //                                                              
2021 //                                                      }
2022 //                                              }
2023 //                                              return false; // when a project is open/closed don't process children
2024 //                                      }
2025 //                                      if ((flags & IResourceDelta.DESCRIPTION) != 0) {
2026 //                                              IProject res = (IProject)delta.getResource();
2027 //                                              JavaModel javaModel = this.manager.getJavaModel();
2028 //                                              boolean wasJavaProject = javaModel.findJavaProject(res) != null;
2029 //                                              boolean isJavaProject = JavaProject.hasJavaNature(res);
2030 //                                              if (wasJavaProject != isJavaProject) {
2031 //                                                      // project's nature has been added or removed
2032 //                                                      element = this.createElement(res, elementType, rootInfo);
2033 //                                                      if (element == null) return false; // note its resources are still visible as roots to other projects
2034 //                                                      if (isJavaProject) {
2035 //                                                              this.elementAdded(element, delta, rootInfo);
2036 //                                                              this.indexManager.indexAll(res);
2037 //                                                      } else {
2038 //                                                              this.elementRemoved(element, delta, rootInfo);
2039 //                                                              this.indexManager.discardJobs(element.getElementName());
2040 //                                                              this.indexManager.removeIndexFamily(res.getFullPath());
2041 //                                                              // reset the corresponding project built state, since cannot reuse if added back
2042 //                                                              this.manager.setLastBuiltState(res, null /*no state*/);
2043 //                                                      }
2044 //                                                      return false; // when a project's nature is added/removed don't process children
2045 //                                              }
2046 //                                      }
2047 //                              }
2048 //                              return true;
2049 //              }
2050 //              return true;
2051 //      }
2052
2053         /**
2054          * Traverse the set of projects which have changed namespace, and refresh their dependents
2055          */
2056 //      public void updateDependentNamelookups() {
2057 //              Iterator iterator;
2058 //              // update namelookup of dependent projects
2059 //              iterator = this.projectsForDependentNamelookupRefresh.iterator();
2060 //              HashSet affectedDependents = new HashSet();
2061 //              while (iterator.hasNext()) {
2062 //                      JavaProject project = (JavaProject)iterator.next();
2063 //                      addDependentProjects(project.getPath(), affectedDependents);
2064 //              }
2065 //              iterator = affectedDependents.iterator();
2066 //              while (iterator.hasNext()) {
2067 //                      JavaProject project = (JavaProject) iterator.next();
2068 //                      if (project.isOpen()){
2069 //                              try {
2070 //                                      ((JavaProjectElementInfo)project.getElementInfo()).setNameLookup(null);
2071 //                              } catch (JavaModelException e) {
2072 //                              }
2073 //                      }
2074 //              }
2075 //      }
2076
2077 //protected void updateIndex(Openable element, IResourceDelta delta) {
2078 //
2079 //      if (indexManager == null)
2080 //              return;
2081 //
2082 //      switch (element.getElementType()) {
2083 //              case IJavaElement.JAVA_PROJECT :
2084 //                      switch (delta.getKind()) {
2085 //                              case IResourceDelta.ADDED :
2086 //                                      this.indexManager.indexAll(element.getJavaProject().getProject());
2087 //                                      break;
2088 //                              case IResourceDelta.REMOVED :
2089 //                                      this.indexManager.removeIndexFamily(element.getJavaProject().getProject().getFullPath());
2090 //                                      // NB: Discarding index jobs belonging to this project was done during PRE_DELETE
2091 //                                      break;
2092 //                              // NB: Update of index if project is opened, closed, or its java nature is added or removed
2093 //                              //     is done in updateCurrentDeltaAndIndex
2094 //                      }
2095 //                      break;
2096 //              case IJavaElement.PACKAGE_FRAGMENT_ROOT :
2097 //                      if (element instanceof JarPackageFragmentRoot) {
2098 //                              JarPackageFragmentRoot root = (JarPackageFragmentRoot)element;
2099 //                              // index jar file only once (if the root is in its declaring project)
2100 //                              IPath jarPath = root.getPath();
2101 //                              switch (delta.getKind()) {
2102 //                                      case IResourceDelta.ADDED:
2103 //                                              // index the new jar
2104 //                                              indexManager.indexLibrary(jarPath, root.getJavaProject().getProject());
2105 //                                              break;
2106 //                                      case IResourceDelta.CHANGED:
2107 //                                              // first remove the index so that it is forced to be re-indexed
2108 //                                              indexManager.removeIndex(jarPath);
2109 //                                              // then index the jar
2110 //                                              indexManager.indexLibrary(jarPath, root.getJavaProject().getProject());
2111 //                                              break;
2112 //                                      case IResourceDelta.REMOVED:
2113 //                                              // the jar was physically removed: remove the index
2114 //                                              this.indexManager.discardJobs(jarPath.toString());
2115 //                                              this.indexManager.removeIndex(jarPath);
2116 //                                              break;
2117 //                              }
2118 //                              break;
2119 //                      } else {
2120 //                              int kind = delta.getKind();
2121 //                              if (kind == IResourceDelta.ADDED || kind == IResourceDelta.REMOVED) {
2122 //                                      IPackageFragmentRoot root = (IPackageFragmentRoot)element;
2123 //                                      this.updateRootIndex(root, root.getPackageFragment(""), delta); //$NON-NLS-1$
2124 //                                      break;
2125 //                              }
2126 //                      }
2127 //                      // don't break as packages of the package fragment root can be indexed below
2128 //              case IJavaElement.PACKAGE_FRAGMENT :
2129 //                      switch (delta.getKind()) {
2130 //                              case IResourceDelta.ADDED:
2131 //                              case IResourceDelta.REMOVED:
2132 //                                      IPackageFragment pkg = null;
2133 //                                      if (element instanceof IPackageFragmentRoot) {
2134 //                                              IPackageFragmentRoot root = (IPackageFragmentRoot)element;
2135 //                                              pkg = root.getPackageFragment(""); //$NON-NLS-1$
2136 //                                      } else {
2137 //                                              pkg = (IPackageFragment)element;
2138 //                                      }
2139 //                                      IResourceDelta[] children = delta.getAffectedChildren();
2140 //                                      for (int i = 0, length = children.length; i < length; i++) {
2141 //                                              IResourceDelta child = children[i];
2142 //                                              IResource resource = child.getResource();
2143 //                                              if (resource instanceof IFile) {
2144 //                                                      String name = resource.getName();
2145 //                                                      if (Util.isJavaFileName(name)) {
2146 //                                                              Openable cu = (Openable)pkg.getCompilationUnit(name);
2147 //                                                              this.updateIndex(cu, child);
2148 //                                                      } else if (Util.isClassFileName(name)) {
2149 //                                                              Openable classFile = (Openable)pkg.getClassFile(name);
2150 //                                                              this.updateIndex(classFile, child);
2151 //                                                      }
2152 //                                              }
2153 //                                      }
2154 //                                      break;
2155 //                      }
2156 //                      break;
2157 //              case IJavaElement.CLASS_FILE :
2158 //                      IFile file = (IFile) delta.getResource();
2159 //                      IJavaProject project = element.getJavaProject();
2160 //                      IPath binaryFolderPath = element.getPackageFragmentRoot().getPath();
2161 //                      // if the class file is part of the binary output, it has been created by
2162 //                      // the java builder -> ignore
2163 //                      try {
2164 //                              if (binaryFolderPath.equals(project.getOutputLocation())) {
2165 //                                      break;
2166 //                              }
2167 //                      } catch (JavaModelException e) {
2168 //                      }
2169 //                      switch (delta.getKind()) {
2170 //                              case IResourceDelta.CHANGED :
2171 //                                      // no need to index if the content has not changed
2172 //                                      if ((delta.getFlags() & IResourceDelta.CONTENT) == 0)
2173 //                                              break;
2174 //                              case IResourceDelta.ADDED :
2175 //                                      indexManager.addBinary(file, binaryFolderPath);
2176 //                                      break;
2177 //                              case IResourceDelta.REMOVED :
2178 //                                      indexManager.remove(file.getFullPath().toString(), binaryFolderPath);
2179 //                                      break;
2180 //                      }
2181 //                      break;
2182 //              case IJavaElement.COMPILATION_UNIT :
2183 //                      file = (IFile) delta.getResource();
2184 //                      switch (delta.getKind()) {
2185 //                              case IResourceDelta.CHANGED :
2186 //                                      // no need to index if the content has not changed
2187 //                                      if ((delta.getFlags() & IResourceDelta.CONTENT) == 0)
2188 //                                              break;
2189 //                              case IResourceDelta.ADDED :
2190 //                                      indexManager.addSource(file, file.getProject().getProject().getFullPath());
2191 //                                      break;
2192 //                              case IResourceDelta.REMOVED :
2193 //                                      indexManager.remove(file.getFullPath().toString(), file.getProject().getProject().getFullPath());
2194 //                                      break;
2195 //                      }
2196 //      }
2197 //}
2198 /**
2199  * Upadtes the index of the given root (assuming it's an addition or a removal).
2200  * This is done recusively, pkg being the current package.
2201  */
2202 //private void updateRootIndex(IPackageFragmentRoot root, IPackageFragment pkg, IResourceDelta delta) {
2203 //      this.updateIndex((Openable)pkg, delta);
2204 //      IResourceDelta[] children = delta.getAffectedChildren();
2205 //      String name = pkg.getElementName();
2206 //      for (int i = 0, length = children.length; i < length; i++) {
2207 //              IResourceDelta child = children[i];
2208 //              IResource resource = child.getResource();
2209 //              if (resource instanceof IFolder) {
2210 //                      String subpkgName = 
2211 //                              name.length() == 0 ? 
2212 //                                      resource.getName() : 
2213 //                                      name + "." + resource.getName(); //$NON-NLS-1$
2214 //                      IPackageFragment subpkg = root.getPackageFragment(subpkgName);
2215 //                      this.updateRootIndex(root, subpkg, child);
2216 //              }
2217 //      }
2218 //}
2219 /*
2220  * Update the roots that are affected by the addition or the removal of the given container resource.
2221  */
2222 //private void updateRoots(IPath containerPath, IResourceDelta containerDelta) {
2223 //      Map roots;
2224 //      Map otherRoots;
2225 //      if (containerDelta.getKind() == IResourceDelta.REMOVED) {
2226 //              roots = this.oldRoots;
2227 //              otherRoots = this.oldOtherRoots;
2228 //      } else {
2229 //              roots = this.roots;
2230 //              otherRoots = this.otherRoots;
2231 //      }
2232 //      Iterator iterator = roots.keySet().iterator();
2233 //      while (iterator.hasNext()) {
2234 //              IPath path = (IPath)iterator.next();
2235 //              if (containerPath.isPrefixOf(path) && !containerPath.equals(path)) {
2236 //                      IResourceDelta rootDelta = containerDelta.findMember(path.removeFirstSegments(1));
2237 //                      if (rootDelta == null) continue;
2238 //                      RootInfo rootInfo = (RootInfo)roots.get(path);
2239 //
2240 //                      if (!rootInfo.project.getPath().isPrefixOf(path)) { // only consider roots that are not included in the container
2241 //                              this.updateCurrentDeltaAndIndex(rootDelta, IJavaElement.PACKAGE_FRAGMENT_ROOT, rootInfo);
2242 //                      }
2243 //                      
2244 //                      ArrayList rootList = (ArrayList)otherRoots.get(path);
2245 //                      if (rootList != null) {
2246 //                              Iterator otherProjects = rootList.iterator();
2247 //                              while (otherProjects.hasNext()) {
2248 //                                      rootInfo = (RootInfo)otherProjects.next();
2249 //                                      if (!rootInfo.project.getPath().isPrefixOf(path)) { // only consider roots that are not included in the container
2250 //                                              this.updateCurrentDeltaAndIndex(rootDelta, IJavaElement.PACKAGE_FRAGMENT_ROOT, rootInfo);
2251 //                                      }
2252 //                              }
2253 //                      }
2254 //              }
2255 //      }
2256 //}
2257
2258 }