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