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