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
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package net.sourceforge.phpdt.internal.core;
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;
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;
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;
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;
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).
61 public class DeltaProcessor implements IResourceChangeListener {
63 final static int IGNORE = 0;
64 final static int SOURCE = 1;
65 final static int BINARY = 2;
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$
73 private final static int NON_JAVA_RESOURCE = -1;
74 public static boolean DEBUG = false;
75 public static boolean VERBOSE = false;
77 public static final int DEFAULT_CHANGE_EVENT = 0; // must not collide with ElementChangedEvent event masks
79 * The <code>JavaElementDelta</code> corresponding to the <code>IResourceDelta</code> being translated.
81 protected JavaElementDelta currentDelta;
83 // protected IndexManager indexManager = new IndexManager();
85 /* A table from IPath (from a classpath entry) to RootInfo */
88 /* A table from IPath (from a classpath entry) to ArrayList of RootInfo
89 * Used when an IPath corresponds to more than one root */
92 /* Whether the roots tables should be recomputed */
93 public boolean rootsAreStale = true;
95 /* A table from IPath (from a classpath entry) to RootInfo
96 * from the last time the delta processor was invoked. */
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 */
104 /* A table from IPath (a source attachment path from a classpath entry) to IPath (a root path) */
105 Map sourceAttachments;
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;
112 * Queue of deltas created explicily by the Java Model that
113 * have yet to be fired.
115 public ArrayList javaModelDeltas= new ArrayList();
117 * Queue of reconcile deltas on working copies that have yet to be fired.
118 * This is a table form IWorkingCopy to IJavaElementDelta
120 public HashMap reconcileDeltas = new HashMap();
123 * Turns delta firing on/off. By default it is on.
125 private boolean isFiring= true;
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();
135 * The global state of delta processing.
137 private DeltaProcessingState state;
140 * The Java model manager
142 private JavaModelManager manager;
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.
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.
153 HashSet refreshedElements;
159 OutputsInfo(IPath[] paths, int[] traverseModes, int outputCount) {
161 this.traverseModes = traverseModes;
162 this.outputCount = outputCount;
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]) {
173 buffer.append("BINARY"); //$NON-NLS-1$
176 buffer.append("IGNORE"); //$NON-NLS-1$
179 buffer.append("SOURCE"); //$NON-NLS-1$
182 buffer.append("<unknown>"); //$NON-NLS-1$
184 if (i+1 < this.outputCount) {
188 return buffer.toString();
192 IJavaProject project;
194 char[][] exclusionPatterns;
195 RootInfo(IJavaProject project, IPath rootPath, char[][] exclusionPatterns) {
196 this.project = project;
197 this.rootPath = rootPath;
198 this.exclusionPatterns = exclusionPatterns;
200 boolean isRootOfProject(IPath path) {
201 return this.rootPath.equals(path) && this.project.getProject().getFullPath().isPrefixOf(path);
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$
208 buffer.append(this.project.getElementName());
210 buffer.append("\npath="); //$NON-NLS-1$
211 if (this.rootPath == null) {
212 buffer.append("null"); //$NON-NLS-1$
214 buffer.append(this.rootPath.toString());
216 buffer.append("\nexcluding="); //$NON-NLS-1$
217 if (this.exclusionPatterns == null) {
218 buffer.append("null"); //$NON-NLS-1$
220 for (int i = 0, length = this.exclusionPatterns.length; i < length; i++) {
221 buffer.append(new String(this.exclusionPatterns[i]));
223 buffer.append("|"); //$NON-NLS-1$
227 return buffer.toString();
231 // DeltaProcessor(JavaModelManager manager) {
232 // this.manager = manager;
236 * Type of event that should be processed no matter what the real event type is.
238 public int overridenEventType = -1;
240 public DeltaProcessor(DeltaProcessingState state, JavaModelManager manager) {
242 this.manager = manager;
245 * Adds the dependents of the given project to the list of the projects
248 // void addDependentProjects(IPath projectPath, HashSet result) {
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);
262 // } catch (JavaModelException e) {
266 * Adds the given element to the list of elements used as a scope for external jars refresh.
268 public void addForRefresh(IJavaElement element) {
269 if (this.refreshedElements == null) {
270 this.refreshedElements = new HashSet();
272 this.refreshedElements.add(element);
275 * Adds the given project and its dependents to the list of the projects
278 void addToProjectsToUpdateWithDependents(IProject project) {
279 this.projectsToUpdate.add(JavaCore.create(project));
280 // this.addDependentProjects(project.getFullPath(), this.projectsToUpdate);
284 * Adds the given child handle to its parent's cache of children.
286 protected void addToParentInfo(Openable child) {
288 Openable parent = (Openable) child.getParent();
289 if (parent != null && parent.isOpen()) {
291 JavaElementInfo info = (JavaElementInfo)parent.getElementInfo();
292 info.addChild(child);
293 } catch (JavaModelException e) {
294 // do nothing - we already checked if open
300 * Check all external archive (referenced by given roots, projects or model) status and issue a corresponding root delta.
301 * Also triggers index updates
303 // public void checkExternalArchiveChanges(IJavaElement[] refreshedElements, IProgressMonitor monitor) throws JavaModelException {
305 // for (int i = 0, length = refreshedElements.length; i < length; i++) {
306 // this.addForRefresh(refreshedElements[i]);
308 // boolean hasDelta = this.createExternalArchiveDelta(monitor);
309 // if (monitor != null && monitor.isCanceled()) return;
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
320 // if (this.currentDelta != null) { // if delta has not been fired while creating markers
321 // this.manager.fire(this.currentDelta, JavaModelManager.DEFAULT_CHANGE_EVENT);
325 // this.currentDelta = null;
326 // if (monitor != null) monitor.done();
330 * Check if external archives have changed and create the corresponding deltas.
331 * Returns whether at least on delta was created.
333 // public boolean createExternalArchiveDelta(IProgressMonitor monitor) throws JavaModelException {
335 // if (this.refreshedElements == null) return false;
337 // HashMap externalArchivesStatus = new HashMap();
338 // boolean hasDelta = false;
340 // // find JARs to refresh
341 // HashSet archivePathsToRefresh = new HashSet();
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());
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
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());
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
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());
382 // this.refreshedElements = null;
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++) {
390 // if (monitor != null && monitor.isCanceled()) break;
392 // IJavaProject project = projects[i];
393 // if (!JavaProject.hasJavaNature(project.getProject())) {
394 // // project is not accessible or has lost its Java nature
397 // IClasspathEntry[] entries = project.getResolvedClasspath(true);
398 // for (int j = 0; j < entries.length; j++){
399 // if (entries[j].getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
401 // IPath entryPath = entries[j].getPath();
403 // if (!archivePathsToRefresh.contains(entryPath)) continue; // not supposed to be refreshed
405 // String status = (String)externalArchivesStatus.get(entryPath);
406 // if (status == null){
408 // // compute shared status
409 // Object targetLibrary = JavaModel.getTarget(wksRoot, entryPath, true);
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);
419 // } else if (targetLibrary instanceof File){ // external JAR
421 // File externalFile = (File)targetLibrary;
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){
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);
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());
442 // externalArchivesStatus.put(entryPath, EXTERNAL_JAR_UNCHANGED);
445 // if (newTimeStamp == 0){ // jar still doesn't exist
446 // externalArchivesStatus.put(entryPath, EXTERNAL_JAR_UNCHANGED);
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());
454 // } else { // internal JAR
455 // externalArchivesStatus.put(entryPath, INTERNAL_JAR_IGNORE);
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());
464 // System.out.println("- External JAR ADDED, affecting root: "+root.getElementName()); //$NON-NLS-1$
466 // elementAdded(root, null, null);
468 // } else if (status == EXTERNAL_JAR_CHANGED) {
469 // PackageFragmentRoot root = (PackageFragmentRoot)project.getPackageFragmentRoot(entryPath.toString());
471 // System.out.println("- External JAR CHANGED, affecting root: "+root.getElementName()); //$NON-NLS-1$
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);
477 // } else if (status == EXTERNAL_JAR_REMOVED) {
478 // PackageFragmentRoot root = (PackageFragmentRoot)project.getPackageFragmentRoot(entryPath.toString());
480 // System.out.println("- External JAR REMOVED, affecting root: "+root.getElementName()); //$NON-NLS-1$
482 // elementRemoved(root, null, null);
491 JavaElementDelta currentDelta() {
492 if (this.currentDelta == null) {
493 this.currentDelta = new JavaElementDelta(this.manager.getJavaModel());
495 return this.currentDelta;
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.
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) {
512 // this.manager.javaProjectsCache = this.manager.getJavaModel().getJavaProjects();
513 // } catch (JavaModelException e) {
517 // IResourceDelta[] children = delta.getAffectedChildren();
518 // for (int i = 0, length = children.length; i < length; i++) {
519 // this.checkProjectsBeingAddedOrRemoved(children[i]);
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);
532 // // workaround for bug 15168 circular errors not reported
533 // if (JavaProject.hasJavaNature(project)) {
534 // this.addToParentInfo((JavaProject)JavaCore.create(project));
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);
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));
549 // JavaProject javaProject = (JavaProject)this.manager.getJavaModel().findJavaProject(project);
550 // if (javaProject != null) {
552 // javaProject.close();
553 // } catch (JavaModelException e) {
555 // this.removeFromParentInfo(javaProject);
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);
565 // // workaround for bug 15168 circular errors not reported
566 // if (isJavaProject) {
567 // this.addToParentInfo((JavaProject)JavaCore.create(project));
569 // JavaProject javaProject = (JavaProject)JavaCore.create(project);
571 // // flush classpath markers
573 // flushClasspathProblemMarkers(
574 // true, // flush cycle markers
575 // true //flush classpath format markers
578 // // remove problems and tasks created by the builder
579 // JavaBuilder.removeProblemsAndTasksFor(project);
583 // javaProject.close();
584 // } catch (JavaModelException e) {
586 // this.removeFromParentInfo(javaProject);
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));
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));
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;
614 // // close the root so that source attachement cache is flushed
615 // root = projectOfRoot.findPackageFragmentRoot(rootPath);
616 // if (root != null) {
619 // } catch (JavaModelException e) {
621 // if (root == null) return;
622 // switch (delta.getKind()) {
623 // case IResourceDelta.ADDED:
624 // currentDelta().sourceAttached(root);
626 // case IResourceDelta.CHANGED:
627 // currentDelta().sourceDetached(root);
628 // currentDelta().sourceAttached(root);
630 // case IResourceDelta.REMOVED:
631 // currentDelta().sourceDetached(root);
639 * Closes the given element, which removes it from the cache of open elements.
641 // protected static void close(Openable element) {
645 // } catch (JavaModelException e) {
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).
655 * Delta argument could be null if processing an external JAR change
657 // protected void contentChanged(Openable element, IResourceDelta delta) {
660 // int flags = IJavaElementDelta.F_CONTENT;
661 // if (element instanceof JarPackageFragmentRoot){
662 // flags |= IJavaElementDelta.F_ARCHIVE_CONTENT_CHANGED;
664 // currentDelta().changed(element, flags);
668 * Creates the openables corresponding to this resource.
669 * Returns null if none was found.
671 // protected Openable createElement(IResource resource, int elementType, RootInfo rootInfo) {
672 // if (resource == null) return null;
674 // IPath path = resource.getFullPath();
675 // IJavaElement element = null;
676 // switch (elementType) {
678 // case IJavaElement.JAVA_PROJECT:
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){
684 // this.popUntilPrefixOf(path);
686 // if (this.currentElement != null
687 // && this.currentElement.getElementType() == IJavaElement.JAVA_PROJECT
688 // && ((IJavaProject)this.currentElement).getProject().equals(resource)) {
689 // return this.currentElement;
691 // if (rootInfo != null && rootInfo.project.getProject().equals(resource)){
692 // element = (Openable)rootInfo.project;
695 // IProject proj = (IProject)resource;
696 // if (JavaProject.hasJavaNature(proj)) {
697 // element = JavaCore.create(proj);
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);
705 // case IJavaElement.PACKAGE_FRAGMENT_ROOT:
706 // element = rootInfo == null ? JavaCore.create(resource) : rootInfo.project.getPackageFragmentRoot(resource);
708 // case IJavaElement.PACKAGE_FRAGMENT:
709 // // find the element that encloses the resource
710 // this.popUntilPrefixOf(path);
712 // if (this.currentElement == null) {
713 // element = rootInfo == null ? JavaCore.create(resource) : JavaModelManager.create(resource, rootInfo.project);
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);
728 // case IJavaElement.COMPILATION_UNIT:
729 // case IJavaElement.CLASS_FILE:
730 // // find the element that encloses the resource
731 // this.popUntilPrefixOf(path);
733 // if (this.currentElement == null) {
734 // element = rootInfo == null ? JavaCore.create(resource) : JavaModelManager.create(resource, rootInfo.project);
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);
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
754 // case IJavaElement.COMPILATION_UNIT:
755 // case IJavaElement.CLASS_FILE:
756 // pkgFragment = (IPackageFragment)this.currentElement.getParent();
759 // if (pkgFragment == null) {
760 // element = rootInfo == null ? JavaCore.create(resource) : JavaModelManager.create(resource, rootInfo.project);
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);
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);
777 // if (element == null) {
780 // this.currentElement = (Openable)element;
781 // return this.currentElement;
785 * Note that the project is about to be deleted.
787 // public void deleting(IProject project) {
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());
794 // JavaProject javaProject = (JavaProject)JavaCore.create(project);
796 // // remember roots of this project
797 // if (this.removedRoots == null) {
798 // this.removedRoots = new HashMap();
800 // if (javaProject.isOpen()) {
801 // this.removedRoots.put(javaProject, javaProject.getPackageFragmentRoots());
803 // // compute roots without opening project
804 // this.removedRoots.put(
806 // javaProject.computePackageFragmentRoots(
807 // javaProject.getResolvedClasspath(true),
811 // javaProject.close();
813 // // workaround for bug 15168 circular errors not reported
814 // if (this.manager.javaProjectsCache == null) {
815 // this.manager.javaProjectsCache = this.manager.getJavaModel().getJavaProjects();
817 // this.removeFromParentInfo(javaProject);
819 // } catch (JavaModelException e) {
822 // this.addDependentProjects(project.getFullPath(), this.projectsToUpdate);
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>.
834 * Delta argument could be null if processing an external JAR change
836 // protected void elementAdded(Openable element, IResourceDelta delta, RootInfo rootInfo) {
837 // int elementType = element.getElementType();
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);
848 // currentDelta().added(element);
850 // this.projectsToUpdate.add(element);
851 // this.updateRoots(element.getPath(), delta);
852 // this.projectsForDependentNamelookupRefresh.add((JavaProject) element);
855 // addToParentInfo(element);
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.
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);
875 // movedFromRes = res.getWorkspace().getRoot().getFolder(movedFromPath);
878 // // find the element type of the moved from element
879 // RootInfo movedFromInfo = this.enclosingRootInfo(movedFromPath, IResourceDelta.REMOVED);
880 // int movedFromType =
883 // IResourceDelta.REMOVED,
884 // element.getParent().getElementType(),
887 // // reset current element as it might be inside a nested root (popUntilPrefixOf() may use the outer root)
888 // this.currentElement = null;
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);
899 // currentDelta().movedTo(element, movedFromElement);
902 // currentDelta().added(element);
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);
913 // case IJavaElement.PACKAGE_FRAGMENT :
914 // // get rid of namelookup since it holds onto obsolete cached info
915 // project = (JavaProject) element.getJavaProject();
917 // project.getJavaProjectElementInfo().setNameLookup(null);
918 // this.projectsForDependentNamelookupRefresh.add(project);
919 // } catch (JavaModelException e) {
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 ?
935 // name + "." + folderName; //$NON-NLS-1$
936 // Openable subpkg = (Openable)root.getPackageFragment(subpkgName);
937 // this.updateIndex(subpkg, child);
938 // this.elementAdded(subpkg, child, rootInfo);
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
954 * Delta argument could be null if processing an external JAR change
956 // protected void elementRemoved(Openable element, IResourceDelta delta, RootInfo rootInfo) {
958 // if (element.isOpen()) {
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());
971 // case IResource.FOLDER:
972 // movedToRes = res.getWorkspace().getRoot().getFolder(movedToPath);
974 // case IResource.FILE:
975 // movedToRes = res.getWorkspace().getRoot().getFile(movedToPath);
981 // // find the element type of the moved from element
982 // RootInfo movedToInfo = this.enclosingRootInfo(movedToPath, IResourceDelta.ADDED);
986 // IResourceDelta.ADDED,
987 // element.getParent().getElementType(),
990 // // reset current element as it might be inside a nested root (popUntilPrefixOf() may use the outer root)
991 // this.currentElement = null;
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);
1002 // currentDelta().movedFrom(element, movedToElement);
1005 // currentDelta().removed(element);
1008 // switch (elementType) {
1009 // case IJavaElement.JAVA_MODEL :
1010 // this.indexManager.reset();
1012 // case IJavaElement.JAVA_PROJECT :
1013 // this.manager.removePerProjectInfo(
1014 // (JavaProject) element);
1015 // this.updateRoots(element.getPath(), delta);
1016 // this.projectsForDependentNamelookupRefresh.add((JavaProject) element);
1018 // case IJavaElement.PACKAGE_FRAGMENT_ROOT :
1019 // JavaProject project = (JavaProject) element.getJavaProject();
1020 // this.projectsToUpdate.add(project);
1021 // this.projectsForDependentNamelookupRefresh.add(project);
1023 // case IJavaElement.PACKAGE_FRAGMENT :
1024 // //1G1TW2T - get rid of namelookup since it holds onto obsolete cached info
1025 // project = (JavaProject) element.getJavaProject();
1027 // project.getJavaProjectElementInfo().setNameLookup(null);
1028 // this.projectsForDependentNamelookupRefresh.add(project);
1029 // } catch (JavaModelException e) {
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 ?
1045 // name + "." + folderName; //$NON-NLS-1$
1046 // Openable subpkg = (Openable)root.getPackageFragment(subpkgName);
1047 // this.updateIndex(subpkg, child);
1048 // this.elementRemoved(subpkg, child, rootInfo);
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)
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);
1071 // if (rootInfo != null && rootInfo.isRootOfProject(res.getFullPath())) {
1072 // return IJavaElement.PACKAGE_FRAGMENT_ROOT;
1074 // return NON_JAVA_RESOURCE; // not yet in a package fragment root or root of another project
1076 // case IJavaElement.PACKAGE_FRAGMENT_ROOT:
1077 // case IJavaElement.PACKAGE_FRAGMENT:
1078 // if (rootInfo == null) {
1079 // rootInfo = this.enclosingRootInfo(res.getFullPath(), kind);
1081 // if (rootInfo == null || Util.isExcluded(res, rootInfo.exclusionPatterns)) {
1082 // return NON_JAVA_RESOURCE;
1084 // if (res instanceof IFolder) {
1085 // if (Util.isValidFolderNameForPackage(res.getName())) {
1086 // return IJavaElement.PACKAGE_FRAGMENT;
1088 // return NON_JAVA_RESOURCE;
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;
1100 // return NON_JAVA_RESOURCE;
1104 // return NON_JAVA_RESOURCE;
1109 * Answer a combination of the lastModified stamp and the size.
1110 * Used for detecting external JAR changes
1112 public static long getTimeStamp(File file) {
1113 return file.lastModified() + file.length();
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;
1121 // recompute root infos only if necessary
1122 if (!rootsAreStale) return;
1124 this.roots = new HashMap();
1125 this.otherRoots = new HashMap();
1126 this.sourceAttachments = new HashMap();
1128 IJavaModel model = this.manager.getJavaModel();
1129 IJavaProject[] projects;
1131 projects = model.getJavaProjects();
1132 } catch (JavaModelException e) {
1133 // nothing can be done
1136 for (int i = 0, length = projects.length; i < length; i++) {
1137 IJavaProject project = projects[i];
1138 IClasspathEntry[] classpath;
1140 classpath = project.getResolvedClasspath(true);
1141 } catch (JavaModelException e) {
1142 // continue with next project
1145 for (int j= 0, classpathLength = classpath.length; j < classpathLength; j++) {
1146 IClasspathEntry entry = classpath[j];
1147 if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) continue;
1150 IPath path = entry.getPath();
1151 if (this.roots.get(path) == null) {
1152 this.roots.put(path, new RootInfo(project, path, ((ClasspathEntry)entry).fullExclusionPatternChars()));
1154 ArrayList rootList = (ArrayList)this.otherRoots.get(path);
1155 if (rootList == null) {
1156 rootList = new ArrayList();
1157 this.otherRoots.put(path, rootList);
1159 rootList.add(new RootInfo(project, path, ((ClasspathEntry)entry).fullExclusionPatternChars()));
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;
1167 propertyString = ResourcesPlugin.getWorkspace().getRoot().getPersistentProperty(qName);
1168 } catch (CoreException e) {
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));
1176 sourceAttachmentPath = entry.getSourceAttachmentPath();
1178 if (sourceAttachmentPath != null) {
1179 this.sourceAttachments.put(sourceAttachmentPath, path);
1183 this.rootsAreStale = false;
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.
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 {}
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();
1213 } catch(FoundRelevantDeltaException e) {
1214 //System.out.println("RELEVANT DELTA detected in: "+ (System.currentTimeMillis() - start));
1216 } catch(CoreException e) { // ignore delta if not able to traverse
1219 //System.out.println("IGNORE SYNC DELTA took: "+ (System.currentTimeMillis() - start));
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.
1227 private boolean isResFilteredFromOutput(OutputsInfo info, IResource res, int elementType) {
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) {
1234 if (info.traverseModes[i] == SOURCE && elementType == IJavaElement.CLASS_FILE) {
1237 // case of .class file under project and no source folder
1239 if (elementType == IJavaElement.JAVA_PROJECT
1240 && res instanceof IFile
1241 && PHPFileUtil.isPHPFile((IFile)res)) {
1254 * Merges all awaiting deltas.
1256 private IJavaElementDelta mergeDeltas(Collection deltas) {
1257 if (deltas.size() == 0) return null;
1258 if (deltas.size() == 1) return (IJavaElementDelta)deltas.iterator().next();
1261 System.out.println("MERGING " + deltas.size() + " DELTAS ["+Thread.currentThread()+"]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
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();
1270 System.out.println(delta.toString());
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;
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;
1288 rootDelta.insertDeltaTree(element, delta);
1289 insertedTree = true;
1292 if (insertedTree) return rootDelta;
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];
1302 System.out.print("Listener #" + (i+1) + "=" + listener.toString());//$NON-NLS-1$//$NON-NLS-2$
1303 start = System.currentTimeMillis();
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$
1310 public void run() throws Exception {
1311 listener.elementChanged(extraEvent);
1315 System.out.println(" -> " + (System.currentTimeMillis()-start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
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).
1327 // protected void nonJavaResourcesChanged(Openable element, IResourceDelta delta)
1328 // throws JavaModelException {
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);
1338 // case IJavaElement.JAVA_PROJECT :
1339 // ((JavaProjectElementInfo) info).setNonJavaResources(null);
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(
1350 // case IJavaElement.PACKAGE_FRAGMENT :
1351 // ((PackageFragmentInfo) info).setNonJavaResources(null);
1353 // case IJavaElement.PACKAGE_FRAGMENT_ROOT :
1354 // ((PackageFragmentRootInfo) info).setNonJavaResources(null);
1358 // JavaElementDelta elementDelta = currentDelta().find(element);
1359 // if (elementDelta == null) {
1360 // currentDelta().changed(element, IJavaElementDelta.F_CONTENT);
1361 // elementDelta = currentDelta().find(element);
1363 // elementDelta.addResourceDelta(delta);
1365 // private OutputsInfo outputsInfo(RootInfo rootInfo, IResource res) {
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);
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;
1393 // traverseModes[outputCount++] = IGNORE;
1397 // // check case of src==bin
1398 // if (entryPath.equals(projectOutput)) {
1399 // traverseModes[0] = (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) ? SOURCE : BINARY;
1402 // return new OutputsInfo(outputs, traverseModes, outputCount);
1405 // } catch (JavaModelException e) {
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.
1417 // public void performPreBuildCheck(
1418 // IResourceDelta delta,
1419 // IJavaElement parent) {
1421 // IResource resource = delta.getResource();
1422 // IJavaElement element = null;
1423 // boolean processChildren = false;
1425 // switch (resource.getType()) {
1427 // case IResource.ROOT :
1428 // if (delta.getKind() == IResourceDelta.CHANGED) {
1429 // element = JavaCore.create(resource);
1430 // processChildren = true;
1433 // case IResource.PROJECT :
1434 // int kind = delta.getKind();
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;
1446 // // remove classpath cache so that initializeRoots() will not consider the project has a classpath
1447 // this.manager.removePerProjectInfo((JavaProject)JavaCore.create(project));
1450 // case IResourceDelta.ADDED:
1451 // this.rootsAreStale = true;
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));
1457 // this.rootsAreStale = true;
1461 // case IResource.FILE :
1462 // if (parent.getElementType() == IJavaElement.JAVA_PROJECT) {
1463 // IFile file = (IFile) resource;
1464 // JavaProject project = (JavaProject) parent;
1466 // /* check classpath file change */
1467 // if (file.getName().equals(JavaProject.CLASSPATH_FILENAME)) {
1468 // reconcileClasspathFileUpdate(delta, file, project);
1469 // this.rootsAreStale = true;
1472 //// /* check custom preference file change */
1473 //// if (file.getName().equals(JavaProject.PREF_FILENAME)) {
1474 //// reconcilePreferenceFileUpdate(delta, file, project);
1480 // if (processChildren) {
1481 // IResourceDelta[] children = delta.getAffectedChildren();
1482 // for (int i = 0; i < children.length; i++) {
1483 // performPreBuildCheck(children[i], element);
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();
1494 // IResource currentElementResource = this.currentElement.getResource();
1495 // if (currentElementResource != null) {
1496 // currentElementPath = currentElementResource.getFullPath();
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();
1506 // if (currentElementPath.isPrefixOf(path)) {
1510 // this.currentElement = (Openable)this.currentElement.getParent();
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.
1519 // public IJavaElementDelta processResourceDelta(IResourceDelta changes) {
1522 // IJavaModel model = this.manager.getJavaModel();
1523 // if (!model.isOpen()) {
1524 // // force opening of java model so that java element delta are reported
1526 // model.open(null);
1527 // } catch (JavaModelException e) {
1529 // e.printStackTrace();
1534 // this.initializeRoots();
1535 // this.currentElement = null;
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();
1543 // // find out the element type
1544 // RootInfo rootInfo = null;
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;
1552 // rootInfo = this.enclosingRootInfo(res.getFullPath(), delta.getKind());
1553 // if (rootInfo != null && rootInfo.isRootOfProject(res.getFullPath())) {
1554 // elementType = IJavaElement.PACKAGE_FRAGMENT_ROOT;
1556 // elementType = IJavaElement.JAVA_PROJECT;
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)
1564 // // add child as non java resource
1565 // nonJavaResourcesChanged((JavaModel)model, delta);
1566 // } catch (JavaModelException e) {
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();
1579 // updateDependentNamelookups();
1581 // return this.currentDelta;
1583 // this.currentDelta = null;
1584 // this.projectsToUpdate.clear();
1585 // this.projectsForDependentNamelookupRefresh.clear();
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)
1593 // void reconcileClasspathFileUpdate(IResourceDelta delta, IFile file, JavaProject project) {
1595 // switch (delta.getKind()) {
1596 // case IResourceDelta.REMOVED : // recreate one based on in-memory classpath
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);
1602 // } catch (JavaModelException e) {
1603 // if (project.getProject().isAccessible()) {
1604 // Util.log(e, "Could not save classpath for "+ project.getPath()); //$NON-NLS-1$
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)
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
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;
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;
1641 // // restore output location
1642 // if (outputLocation == null) {
1643 // outputLocation = SetClasspathOperation.ReuseOutputLocation;
1644 // // clean mode will also default to reusing current one
1646 // project.setRawClasspath(
1650 // true, // canChangeResource
1651 // project.getResolvedClasspath(true), // ignoreUnresolvedVariable
1652 // true, // needValidation
1653 // false); // no need to save
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$
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$
1671 // project.createClasspathProblemMarker(new JavaModelStatus(
1672 // IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
1673 // Util.bind("classpath.invalidClasspathInClasspathFile", project.getElementName(), e.getMessage()))); //$NON-NLS-1$
1678 // if (!wasSuccessful) {
1680 // project.setRawClasspath0(JavaProject.INVALID_CLASSPATH);
1681 // project.updatePackageFragmentRoots();
1682 // } catch (JavaModelException e) {
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)
1694 // void reconcilePreferenceFileUpdate(IResourceDelta delta, IFile file, JavaProject project) {
1696 // switch (delta.getKind()) {
1697 // case IResourceDelta.REMOVED : // flush project custom settings
1698 // project.setOptions(null);
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
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.
1711 // Preferences projectPreferences = project.getPreferences();
1712 // if (projectPreferences == null) return; // not a Java project
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;
1724 // } else break identityCheck;
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;
1736 // } else break identityCheck;
1738 // // identical - do nothing
1741 // case IResourceDelta.ADDED :
1742 // // not identical, create delta and reset cached preferences
1743 // project.setPreferences(null);
1745 // //fCurrentDelta.changed(project, IJavaElementDelta.F_OPTIONS_CHANGED);
1749 * Registers the given delta with this delta processor.
1751 public void registerJavaModelDelta(IJavaElementDelta delta) {
1752 this.javaModelDeltas.add(delta);
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.
1759 protected void removeFromParentInfo(Openable child) {
1761 Openable parent = (Openable) child.getParent();
1762 if (parent != null && parent.isOpen()) {
1764 JavaElementInfo info = (JavaElementInfo)parent.getElementInfo();
1765 info.removeChild(child);
1766 } catch (JavaModelException e) {
1767 // do nothing - we already checked if open
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>.
1778 * @see IResourceDelta
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();
1789 case IResourceChangeEvent.PRE_DELETE :
1791 if(resource.getType() == IResource.PROJECT
1792 && ((IProject) resource).hasNature(PHPeclipsePlugin.PHP_NATURE_ID)) {
1793 // TODO jsurfer temp-del
1794 // this.deleting((IProject)resource);
1796 } catch(CoreException e){
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);
1805 // // update the classpath related markers
1806 // this.updateClasspathMarkers();
1808 // // the following will close project if affected by the property file change
1810 // // don't fire classpath change deltas right away, but batch them
1811 // this.manager.stopDeltas();
1812 // this.performPreBuildCheck(delta, null);
1814 // this.manager.startDeltas();
1817 // only fire already computed deltas (resource ones will be processed in post change only)
1818 this.manager.fire(null, ElementChangedEvent.PRE_AUTO_BUILD);
1821 case IResourceChangeEvent.POST_AUTO_BUILD :
1822 // TODO jsurfer temp-del
1823 // JavaBuilder.finishedBuilding(event);
1826 case IResourceChangeEvent.POST_CHANGE :
1827 // TODO jsurfer temp-del
1828 // if (isAffectedBy(delta)) {
1830 // if (this.refreshedElements != null) {
1832 // createExternalArchiveDelta(null);
1833 // } catch (JavaModelException e) {
1834 // e.printStackTrace();
1837 // IJavaElementDelta translatedDelta = this.processResourceDelta(delta);
1838 // if (translatedDelta != null) {
1839 // this.manager.registerJavaModelDelta(translatedDelta);
1841 // this.manager.fire(null, ElementChangedEvent.POST_CHANGE);
1843 // // workaround for bug 15168 circular errors not reported
1844 // this.manager.javaProjectsCache = null;
1845 // this.removedRoots = null;
1852 * Flushes all deltas without firing them.
1854 public void flush() {
1855 this.javaModelDeltas = new ArrayList();
1858 * Finds the root info this path is included in.
1859 * Returns null if not found.
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);
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.
1873 public void fire(IJavaElementDelta customDelta, int eventType) {
1874 if (!this.isFiring) return;
1877 System.out.println("-----------------------------------------------------------------------------------------------------------------------");//$NON-NLS-1$
1880 IJavaElementDelta deltaToNotify;
1881 if (customDelta == null){
1882 deltaToNotify = this.mergeDeltas(this.javaModelDeltas);
1884 deltaToNotify = customDelta;
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);
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;
1904 switch (eventType) {
1905 case DEFAULT_CHANGE_EVENT:
1906 firePostChangeDelta(deltaToNotify, listeners, listenerMask, listenerCount);
1907 fireReconcileDelta(listeners, listenerMask, listenerCount);
1909 case ElementChangedEvent.POST_CHANGE:
1910 firePostChangeDelta(deltaToNotify, listeners, listenerMask, listenerCount);
1911 fireReconcileDelta(listeners, listenerMask, listenerCount);
1916 private void firePostChangeDelta(
1917 IJavaElementDelta deltaToNotify,
1918 IElementChangedListener[] listeners,
1920 int listenerCount) {
1922 // post change deltas
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$
1927 if (deltaToNotify != null) {
1928 // flush now so as to keep listener reactions to post their own deltas for subsequent iteration
1931 notifyListeners(deltaToNotify, ElementChangedEvent.POST_CHANGE, listeners, listenerMask, listenerCount);
1934 private void fireReconcileDelta(
1935 IElementChangedListener[] listeners,
1937 int listenerCount) {
1940 IJavaElementDelta deltaToNotify = mergeDeltas(this.reconcileDeltas.values());
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$
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();
1949 notifyListeners(deltaToNotify, ElementChangedEvent.POST_RECONCILE, listeners, listenerMask, listenerCount);
1953 * Returns the root info for the given path. Look in the old roots table if kind is REMOVED.
1955 RootInfo rootInfo(IPath path, int kind) {
1956 if (kind == IResourceDelta.REMOVED) {
1957 return (RootInfo)this.oldRoots.get(path);
1959 return (RootInfo)this.roots.get(path);
1963 * Returns the other root infos for the given path. Look in the old other roots table if kind is REMOVED.
1965 ArrayList otherRootsInfo(IPath path, int kind) {
1966 if (kind == IResourceDelta.REMOVED) {
1967 return (ArrayList)this.oldOtherRoots.get(path);
1969 return (ArrayList)this.otherRoots.get(path);
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.
1980 // protected boolean traverseDelta(
1981 // IResourceDelta delta,
1983 // RootInfo rootInfo,
1984 // OutputsInfo outputsInfo) {
1986 // IResource res = delta.getResource();
1988 // // set stack of elements
1989 // if (this.currentElement == null && rootInfo != null) {
1990 // this.currentElement = (Openable)rootInfo.project;
1993 // // process current delta
1994 // boolean processChildren = true;
1995 // if (res instanceof IProject) {
1996 // processChildren =
1997 // this.updateCurrentDeltaAndIndex(
1999 // elementType == IJavaElement.PACKAGE_FRAGMENT_ROOT ?
2000 // IJavaElement.JAVA_PROJECT : // case of prj=src
2003 // } else if (rootInfo != null) {
2004 // processChildren = this.updateCurrentDeltaAndIndex(delta, elementType, rootInfo);
2006 // // not yet inside a package fragment root
2007 // processChildren = true;
2010 // // get the project's output locations and traverse mode
2011 // if (outputsInfo == null) outputsInfo = this.outputsInfo(rootInfo, res);
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();
2025 // // check source attachment change
2026 // this.checkSourceAttachmentChange(child, childRes);
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;
2037 // // compute child type
2039 // this.elementType(
2043 // rootInfo == null ? childRootInfo : rootInfo
2046 // // is childRes in the output folder and is it filtered out ?
2047 // boolean isResFilteredFromOutput = this.isResFilteredFromOutput(outputsInfo, childRes, childType);
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
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;
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;
2070 // parent = this.createElement(res, elementType, rootInfo);
2072 // if (parent == null) {
2073 // isValidParent = false;
2077 // // add child as non java resource
2078 // nonJavaResourcesChanged(parent, child);
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;
2084 // } catch (JavaModelException e) {
2087 // oneChildOnClasspath = true;
2090 // oneChildOnClasspath = true; // to avoid reporting child delta as non-java resource delta
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
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
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
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
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) {
2124 // nonJavaResourcesChanged(adoptiveProject, orphanChildren[i]);
2125 // } catch (JavaModelException e) {
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)
2133 // return elementType != NON_JAVA_RESOURCE;
2138 * Update the classpath markers and cycle markers for the projects to update.
2140 // void updateClasspathMarkers() {
2142 // if (!ResourcesPlugin.getWorkspace().isAutoBuilding()) {
2143 // Iterator iterator = this.projectsToUpdate.iterator();
2144 // while (iterator.hasNext()) {
2146 // JavaProject project = (JavaProject)iterator.next();
2148 // // force classpath marker refresh
2149 // project.getResolvedClasspath(
2150 // true, // ignoreUnresolvedEntry
2151 // true); // generateMarkerOnError
2153 // } catch (JavaModelException e) {
2157 // if (!this.projectsToUpdate.isEmpty()){
2159 // // update all cycle markers
2160 // JavaProject.updateAllCycleMarkers();
2161 // } catch (JavaModelException e) {
2165 // this.projectsToUpdate = new HashSet();
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.
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);
2185 // this.updateIndex(element, delta);
2186 // this.elementAdded(element, delta, rootInfo);
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);
2196 // this.updateIndex(element, delta);
2197 // this.elementRemoved(element, delta, rootInfo);
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*/);
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);
2222 // if (res.isOpen()) {
2223 // if (JavaProject.hasJavaNature(res)) {
2224 // this.elementAdded(element, delta, rootInfo);
2225 // this.indexManager.indexAll(res);
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());
2237 // return false; // when a project is open/closed don't process children
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);
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*/);
2258 // return false; // when a project's nature is added/removed don't process children
2268 * Traverse the set of projects which have changed namespace, and refresh their dependents
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);
2279 // iterator = affectedDependents.iterator();
2280 // while (iterator.hasNext()) {
2281 // JavaProject project = (JavaProject) iterator.next();
2282 // if (project.isOpen()){
2284 // ((JavaProjectElementInfo)project.getElementInfo()).setNameLookup(null);
2285 // } catch (JavaModelException e) {
2291 //protected void updateIndex(Openable element, IResourceDelta delta) {
2293 // if (indexManager == null)
2296 // switch (element.getElementType()) {
2297 // case IJavaElement.JAVA_PROJECT :
2298 // switch (delta.getKind()) {
2299 // case IResourceDelta.ADDED :
2300 // this.indexManager.indexAll(element.getJavaProject().getProject());
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
2306 // // NB: Update of index if project is opened, closed, or its java nature is added or removed
2307 // // is done in updateCurrentDeltaAndIndex
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());
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());
2326 // case IResourceDelta.REMOVED:
2327 // // the jar was physically removed: remove the index
2328 // this.indexManager.discardJobs(jarPath.toString());
2329 // this.indexManager.removeIndex(jarPath);
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$
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$
2351 // pkg = (IPackageFragment)element;
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);
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
2378 // if (binaryFolderPath.equals(project.getOutputLocation())) {
2381 // } catch (JavaModelException e) {
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)
2388 // case IResourceDelta.ADDED :
2389 // indexManager.addBinary(file, binaryFolderPath);
2391 // case IResourceDelta.REMOVED :
2392 // indexManager.remove(file.getFullPath().toString(), binaryFolderPath);
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)
2403 // case IResourceDelta.ADDED :
2404 // indexManager.addSource(file, file.getProject().getProject().getFullPath());
2406 // case IResourceDelta.REMOVED :
2407 // indexManager.remove(file.getFullPath().toString(), file.getProject().getProject().getFullPath());
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.
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);
2434 * Update the roots that are affected by the addition or the removal of the given container resource.
2436 //private void updateRoots(IPath containerPath, IResourceDelta containerDelta) {
2439 // if (containerDelta.getKind() == IResourceDelta.REMOVED) {
2440 // roots = this.oldRoots;
2441 // otherRoots = this.oldOtherRoots;
2443 // roots = this.roots;
2444 // otherRoots = this.otherRoots;
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);
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);
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);