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