/*******************************************************************************
* Copyright (c) 2000, 2003 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package net.sourceforge.phpdt.internal.core;
//import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import net.sourceforge.phpdt.core.ElementChangedEvent;
//import net.sourceforge.phpdt.core.IClasspathEntry;
import net.sourceforge.phpdt.core.IElementChangedListener;
import net.sourceforge.phpdt.core.IJavaElement;
import net.sourceforge.phpdt.core.IJavaElementDelta;
import net.sourceforge.phpdt.core.IJavaModel;
import net.sourceforge.phpdt.core.IJavaProject;
import net.sourceforge.phpdt.core.JavaCore;
import net.sourceforge.phpdt.core.JavaModelException;
import net.sourceforge.phpdt.internal.core.builder.PHPBuilder;
import net.sourceforge.phpdt.internal.core.util.Util;
//import net.sourceforge.phpdt.internal.core.util.PHPFileUtil;
import net.sourceforge.phpeclipse.PHPeclipsePlugin;
//import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.IWorkspace;
//import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.ISafeRunnable;
//import org.eclipse.core.runtime.Platform;
//import org.eclipse.core.runtime.QualifiedName;
import org.eclipse.core.runtime.SafeRunner;
/**
* This class is used by JavaModelManager
to convert
* IResourceDelta
s into IJavaElementDelta
s. It
* also does some processing on the JavaElement
s involved (e.g.
* closing them or updating classpaths).
*/
public class DeltaProcessor implements IResourceChangeListener {
final static int IGNORE = 0;
final static int SOURCE = 1;
final static int BINARY = 2;
final static String EXTERNAL_JAR_ADDED = "external jar added"; //$NON-NLS-1$
final static String EXTERNAL_JAR_REMOVED = "external jar removed"; //$NON-NLS-1$
final static String EXTERNAL_JAR_CHANGED = "external jar changed"; //$NON-NLS-1$
final static String EXTERNAL_JAR_UNCHANGED = "external jar unchanged"; //$NON-NLS-1$
final static String INTERNAL_JAR_IGNORE = "internal jar ignore"; //$NON-NLS-1$
private final static int NON_JAVA_RESOURCE = -1;
public static boolean DEBUG = false;
public static boolean VERBOSE = false;
public static final int DEFAULT_CHANGE_EVENT = 0; // must not collide with
// ElementChangedEvent
// event masks
/**
* The JavaElementDelta
corresponding to the
* IResourceDelta
being translated.
*/
protected JavaElementDelta currentDelta;
// protected IndexManager indexManager = new IndexManager();
/* A table from IPath (from a classpath entry) to RootInfo */
public Map roots;
/*
* A table from IPath (from a classpath entry) to ArrayList of RootInfo Used
* when an IPath corresponds to more than one root
*/
Map otherRoots;
/* Whether the roots tables should be recomputed */
public boolean rootsAreStale = true;
/*
* A table from IPath (from a classpath entry) to RootInfo from the last
* time the delta processor was invoked.
*/
public Map oldRoots;
/*
* A table from IPath (from a classpath entry) to ArrayList of RootInfo from
* the last time the delta processor was invoked. Used when an IPath
* corresponds to more than one root
*/
Map oldOtherRoots;
/*
* A table from IPath (a source attachment path from a classpath entry) to
* IPath (a root path)
*/
Map sourceAttachments;
/*
* The java element that was last created (see createElement(IResource)).
* This is used as a stack of java elements (using getParent() to pop it,
* and using the various get*(...) to push it.
*/
Openable currentElement;
/*
* Queue of deltas created explicily by the Java Model that have yet to be
* fired.
*/
public ArrayList javaModelDeltas = new ArrayList();
/*
* Queue of reconcile deltas on working copies that have yet to be fired.
* This is a table form IWorkingCopy to IJavaElementDelta
*/
public HashMap reconcileDeltas = new HashMap();
/*
* Turns delta firing on/off. By default it is on.
*/
private boolean isFiring = true;
public HashMap externalTimeStamps = new HashMap();
public HashSet projectsToUpdate = new HashSet();
// list of root projects which namelookup caches need to be updated for
// dependents
// TODO: (jerome) is it needed? projectsToUpdate might be sufficient
public HashSet projectsForDependentNamelookupRefresh = new HashSet();
/*
* The global state of delta processing.
*/
private DeltaProcessingState state;
/*
* The Java model manager
*/
private JavaModelManager manager;
/*
* A table from IJavaProject to an array of IPackageFragmentRoot. This table
* contains the pkg fragment roots of the project that are being deleted.
*/
Map removedRoots;
/*
* A list of IJavaElement used as a scope for external archives refresh
* during POST_CHANGE. This is null if no refresh is needed.
*/
HashSet refreshedElements;
class OutputsInfo {
IPath[] paths;
int[] traverseModes;
int outputCount;
OutputsInfo(IPath[] paths, int[] traverseModes, int outputCount) {
this.paths = paths;
this.traverseModes = traverseModes;
this.outputCount = outputCount;
}
public String toString() {
if (this.paths == null)
return ""; //$NON-NLS-1$
StringBuffer buffer = new StringBuffer();
for (int i = 0; i < this.outputCount; i++) {
buffer.append("path="); //$NON-NLS-1$
buffer.append(this.paths[i].toString());
buffer.append("\n->traverse="); //$NON-NLS-1$
switch (this.traverseModes[i]) {
case BINARY:
buffer.append("BINARY"); //$NON-NLS-1$
break;
case IGNORE:
buffer.append("IGNORE"); //$NON-NLS-1$
break;
case SOURCE:
buffer.append("SOURCE"); //$NON-NLS-1$
break;
default:
buffer.append(""); //$NON-NLS-1$
}
if (i + 1 < this.outputCount) {
buffer.append('\n');
}
}
return buffer.toString();
}
}
class RootInfo {
IJavaProject project;
IPath rootPath;
char[][] exclusionPatterns;
RootInfo(IJavaProject project, IPath rootPath,
char[][] exclusionPatterns) {
this.project = project;
this.rootPath = rootPath;
this.exclusionPatterns = exclusionPatterns;
}
boolean isRootOfProject(IPath path) {
return this.rootPath.equals(path)
&& this.project.getProject().getFullPath().isPrefixOf(path);
}
public String toString() {
StringBuffer buffer = new StringBuffer("project="); //$NON-NLS-1$
if (this.project == null) {
buffer.append("null"); //$NON-NLS-1$
} else {
buffer.append(this.project.getElementName());
}
buffer.append("\npath="); //$NON-NLS-1$
if (this.rootPath == null) {
buffer.append("null"); //$NON-NLS-1$
} else {
buffer.append(this.rootPath.toString());
}
buffer.append("\nexcluding="); //$NON-NLS-1$
if (this.exclusionPatterns == null) {
buffer.append("null"); //$NON-NLS-1$
} else {
for (int i = 0, length = this.exclusionPatterns.length; i < length; i++) {
buffer.append(new String(this.exclusionPatterns[i]));
if (i < length - 1) {
buffer.append("|"); //$NON-NLS-1$
}
}
}
return buffer.toString();
}
}
// DeltaProcessor(JavaModelManager manager) {
// this.manager = manager;
// }
/*
* Type of event that should be processed no matter what the real event type
* is.
*/
public int overridenEventType = -1;
public DeltaProcessor(DeltaProcessingState state, JavaModelManager manager) {
this.state = state;
this.manager = manager;
}
/*
* Adds the dependents of the given project to the list of the projects to
* update.
*/
// void addDependentProjects(IPath projectPath, HashSet result) {
// try {
// IJavaProject[] projects = this.manager.getJavaModel().getJavaProjects();
// for (int i = 0, length = projects.length; i < length; i++) {
// IJavaProject project = projects[i];
// IClasspathEntry[] classpath =
// ((JavaProject)project).getExpandedClasspath(true);
// for (int j = 0, length2 = classpath.length; j < length2; j++) {
// IClasspathEntry entry = classpath[j];
// if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT
// && entry.getPath().equals(projectPath)) {
// result.add(project);
// }
// }
// }
// } catch (JavaModelException e) {
// }
// }
/*
* Adds the given element to the list of elements used as a scope for
* external jars refresh.
*/
public void addForRefresh(IJavaElement element) {
if (this.refreshedElements == null) {
this.refreshedElements = new HashSet();
}
this.refreshedElements.add(element);
}
/*
* Adds the given project and its dependents to the list of the projects to
* update.
*/
// void addToProjectsToUpdateWithDependents(IProject project) {
// this.projectsToUpdate.add(JavaCore.create(project));
// // this.addDependentProjects(project.getFullPath(),
// // this.projectsToUpdate);
// }
/**
* Adds the given child handle to its parent's cache of children.
*/
// protected void addToParentInfo(Openable child) {
//
// Openable parent = (Openable) child.getParent();
// if (parent != null && parent.isOpen()) {
// try {
// JavaElementInfo info = (JavaElementInfo) parent
// .getElementInfo();
// info.addChild(child);
// } catch (JavaModelException e) {
// // do nothing - we already checked if open
// }
// }
// }
/**
* Check all external archive (referenced by given roots, projects or model)
* status and issue a corresponding root delta. Also triggers index updates
*/
// public void checkExternalArchiveChanges(IJavaElement[] refreshedElements,
// IProgressMonitor monitor) throws JavaModelException {
// try {
// for (int i = 0, length = refreshedElements.length; i < length; i++) {
// this.addForRefresh(refreshedElements[i]);
// }
// boolean hasDelta = this.createExternalArchiveDelta(monitor);
// if (monitor != null && monitor.isCanceled()) return;
// if (hasDelta){
// // force classpath marker refresh of affected projects
// JavaModel.flushExternalFileCache();
// IJavaElementDelta[] projectDeltas =
// this.currentDelta.getAffectedChildren();
// for (int i = 0, length = projectDeltas.length; i < length; i++) {
// IJavaElementDelta delta = projectDeltas[i];
// ((JavaProject)delta.getElement()).getResolvedClasspath(
// true, // ignoreUnresolvedEntry
// true); // generateMarkerOnError
// }
// if (this.currentDelta != null) { // if delta has not been fired while
// creating markers
// this.manager.fire(this.currentDelta,
// JavaModelManager.DEFAULT_CHANGE_EVENT);
// }
// }
// } finally {
// this.currentDelta = null;
// if (monitor != null) monitor.done();
// }
// }
/*
* Check if external archives have changed and create the corresponding
* deltas. Returns whether at least on delta was created.
*/
// public boolean createExternalArchiveDelta(IProgressMonitor monitor)
// throws JavaModelException {
//
// if (this.refreshedElements == null) return false;
//
// HashMap externalArchivesStatus = new HashMap();
// boolean hasDelta = false;
//
// // find JARs to refresh
// HashSet archivePathsToRefresh = new HashSet();
// try {
// Iterator iterator = this.refreshedElements.iterator();
// while (iterator.hasNext()) {
// IJavaElement element = (IJavaElement)iterator.next();
// switch(element.getElementType()){
// case IJavaElement.PACKAGE_FRAGMENT_ROOT :
// archivePathsToRefresh.add(element.getPath());
// break;
// case IJavaElement.JAVA_PROJECT :
// IJavaProject project = (IJavaProject) element;
// if (!JavaProject.hasJavaNature(project.getProject())) {
// // project is not accessible or has lost its Java nature
// break;
// }
// IClasspathEntry[] classpath = project.getResolvedClasspath(true);
// for (int j = 0, cpLength = classpath.length; j < cpLength; j++){
// if (classpath[j].getEntryKind() == IClasspathEntry.CPE_LIBRARY){
// archivePathsToRefresh.add(classpath[j].getPath());
// }
// }
// break;
// case IJavaElement.JAVA_MODEL :
// IJavaProject[] projects =
// manager.getJavaModel().getOldJavaProjectsList();
// for (int j = 0, projectsLength = projects.length; j < projectsLength;
// j++){
// project = projects[j];
// if (!JavaProject.hasJavaNature(project.getProject())) {
// // project is not accessible or has lost its Java nature
// continue;
// }
// classpath = project.getResolvedClasspath(true);
// for (int k = 0, cpLength = classpath.length; k < cpLength; k++){
// if (classpath[k].getEntryKind() == IClasspathEntry.CPE_LIBRARY){
// archivePathsToRefresh.add(classpath[k].getPath());
// }
// }
// }
// break;
// }
// }
// } finally {
// this.refreshedElements = null;
// }
//
// // perform refresh
// IJavaProject[] projects =
// manager.getJavaModel().getOldJavaProjectsList();
// IWorkspaceRoot wksRoot = ResourcesPlugin.getWorkspace().getRoot();
// for (int i = 0, length = projects.length; i < length; i++) {
//
// if (monitor != null && monitor.isCanceled()) break;
//
// IJavaProject project = projects[i];
// if (!JavaProject.hasJavaNature(project.getProject())) {
// // project is not accessible or has lost its Java nature
// continue;
// }
// IClasspathEntry[] entries = project.getResolvedClasspath(true);
// for (int j = 0; j < entries.length; j++){
// if (entries[j].getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
//
// IPath entryPath = entries[j].getPath();
//
// if (!archivePathsToRefresh.contains(entryPath)) continue; // not supposed
// to be refreshed
//
// String status = (String)externalArchivesStatus.get(entryPath);
// if (status == null){
//
// // compute shared status
// Object targetLibrary = JavaModel.getTarget(wksRoot, entryPath, true);
//
// if (targetLibrary == null){ // missing JAR
// if (this.externalTimeStamps.containsKey(entryPath)){
// this.externalTimeStamps.remove(entryPath);
// externalArchivesStatus.put(entryPath, EXTERNAL_JAR_REMOVED);
// // the jar was physically removed: remove the index
// indexManager.removeIndex(entryPath);
// }
//
// } else if (targetLibrary instanceof File){ // external JAR
//
// File externalFile = (File)targetLibrary;
//
// // check timestamp to figure if JAR has changed in some way
// Long oldTimestamp =(Long) this.externalTimeStamps.get(entryPath);
// long newTimeStamp = getTimeStamp(externalFile);
// if (oldTimestamp != null){
//
// if (newTimeStamp == 0){ // file doesn't exist
// externalArchivesStatus.put(entryPath, EXTERNAL_JAR_REMOVED);
// this.externalTimeStamps.remove(entryPath);
// // remove the index
// indexManager.removeIndex(entryPath);
//
// } else if (oldTimestamp.longValue() != newTimeStamp){
// externalArchivesStatus.put(entryPath, EXTERNAL_JAR_CHANGED);
// this.externalTimeStamps.put(entryPath, new Long(newTimeStamp));
// // first remove the index so that it is forced to be re-indexed
// indexManager.removeIndex(entryPath);
// // then index the jar
// indexManager.indexLibrary(entryPath, project.getProject());
// } else {
// externalArchivesStatus.put(entryPath, EXTERNAL_JAR_UNCHANGED);
// }
// } else {
// if (newTimeStamp == 0){ // jar still doesn't exist
// externalArchivesStatus.put(entryPath, EXTERNAL_JAR_UNCHANGED);
// } else {
// externalArchivesStatus.put(entryPath, EXTERNAL_JAR_ADDED);
// this.externalTimeStamps.put(entryPath, new Long(newTimeStamp));
// // index the new jar
// indexManager.indexLibrary(entryPath, project.getProject());
// }
// }
// } else { // internal JAR
// externalArchivesStatus.put(entryPath, INTERNAL_JAR_IGNORE);
// }
// }
// // according to computed status, generate a delta
// status = (String)externalArchivesStatus.get(entryPath);
// if (status != null){
// if (status == EXTERNAL_JAR_ADDED){
// PackageFragmentRoot root =
// (PackageFragmentRoot)project.getPackageFragmentRoot(entryPath.toString());
// if (VERBOSE){
// System.out.println("- External JAR ADDED, affecting root:
// "+root.getElementName()); //$NON-NLS-1$
// }
// elementAdded(root, null, null);
// hasDelta = true;
// } else if (status == EXTERNAL_JAR_CHANGED) {
// PackageFragmentRoot root =
// (PackageFragmentRoot)project.getPackageFragmentRoot(entryPath.toString());
// if (VERBOSE){
// System.out.println("- External JAR CHANGED, affecting root:
// "+root.getElementName()); //$NON-NLS-1$
// }
// // reset the corresponding project built state, since the builder would
// miss this change
// this.manager.setLastBuiltState(project.getProject(), null /*no state*/);
// contentChanged(root, null);
// hasDelta = true;
// } else if (status == EXTERNAL_JAR_REMOVED) {
// PackageFragmentRoot root =
// (PackageFragmentRoot)project.getPackageFragmentRoot(entryPath.toString());
// if (VERBOSE){
// System.out.println("- External JAR REMOVED, affecting root:
// "+root.getElementName()); //$NON-NLS-1$
// }
// elementRemoved(root, null, null);
// hasDelta = true;
// }
// }
// }
// }
// }
// return hasDelta;
// }
JavaElementDelta currentDelta() {
if (this.currentDelta == null) {
this.currentDelta = new JavaElementDelta(this.manager
.getJavaModel());
}
return this.currentDelta;
}
/*
* Process the given delta and look for projects being added, opened, closed
* or with a java nature being added or removed. Note that projects being
* deleted are checked in deleting(IProject). In all cases, add the
* project's dependents to the list of projects to update so that the
* classpath related markers can be updated.
*/
// public void checkProjectsBeingAddedOrRemoved(IResourceDelta delta) {
// IResource resource = delta.getResource();
// switch (resource.getType()) {
// case IResource.ROOT :
// // workaround for bug 15168 circular errors not reported
// if (this.manager.javaProjectsCache == null) {
// try {
// this.manager.javaProjectsCache =
// this.manager.getJavaModel().getJavaProjects();
// } catch (JavaModelException e) {
// }
// }
//
// IResourceDelta[] children = delta.getAffectedChildren();
// for (int i = 0, length = children.length; i < length; i++) {
// this.checkProjectsBeingAddedOrRemoved(children[i]);
// }
// break;
// case IResource.PROJECT :
// // NB: No need to check project's nature as if the project is not a java
// project:
// // - if the project is added or changed this is a noop for
// projectsBeingDeleted
// // - if the project is closed, it has already lost its java nature
// int deltaKind = delta.getKind();
// if (deltaKind == IResourceDelta.ADDED) {
// // remember project and its dependents
// IProject project = (IProject)resource;
// this.addToProjectsToUpdateWithDependents(project);
//
// // workaround for bug 15168 circular errors not reported
// if (JavaProject.hasJavaNature(project)) {
// this.addToParentInfo((JavaProject)JavaCore.create(project));
// }
//
// } else if (deltaKind == IResourceDelta.CHANGED) {
// IProject project = (IProject)resource;
// if ((delta.getFlags() & IResourceDelta.OPEN) != 0) {
// // project opened or closed: remember project and its dependents
// this.addToProjectsToUpdateWithDependents(project);
//
// // workaround for bug 15168 circular errors not reported
// if (project.isOpen()) {
// if (JavaProject.hasJavaNature(project)) {
// this.addToParentInfo((JavaProject)JavaCore.create(project));
// }
// } else {
// JavaProject javaProject =
// (JavaProject)this.manager.getJavaModel().findJavaProject(project);
// if (javaProject != null) {
// try {
// javaProject.close();
// } catch (JavaModelException e) {
// }
// this.removeFromParentInfo(javaProject);
// }
// }
// } else if ((delta.getFlags() & IResourceDelta.DESCRIPTION) != 0) {
// boolean wasJavaProject =
// this.manager.getJavaModel().findJavaProject(project) != null;
// boolean isJavaProject = JavaProject.hasJavaNature(project);
// if (wasJavaProject != isJavaProject) {
// // java nature added or removed: remember project and its dependents
// this.addToProjectsToUpdateWithDependents(project);
//
// // workaround for bug 15168 circular errors not reported
// if (isJavaProject) {
// this.addToParentInfo((JavaProject)JavaCore.create(project));
// } else {
// JavaProject javaProject = (JavaProject)JavaCore.create(project);
//
// // flush classpath markers
// javaProject.
// flushClasspathProblemMarkers(
// true, // flush cycle markers
// true //flush classpath format markers
// );
//
// // remove problems and tasks created by the builder
// JavaBuilder.removeProblemsAndTasksFor(project);
//
// // close project
// try {
// javaProject.close();
// } catch (JavaModelException e) {
// }
// this.removeFromParentInfo(javaProject);
// }
// } else {
// // in case the project was removed then added then changed (see bug
// 19799)
// if (JavaProject.hasJavaNature(project)) { // need nature check - 18698
// this.addToParentInfo((JavaProject)JavaCore.create(project));
// }
// }
// } else {
// // workaround for bug 15168 circular errors not reported
// // in case the project was removed then added then changed
// if (JavaProject.hasJavaNature(project)) { // need nature check - 18698
// this.addToParentInfo((JavaProject)JavaCore.create(project));
// }
// }
// }
// break;
// }
// }
// private void checkSourceAttachmentChange(IResourceDelta delta, IResource
// res) {
// IPath rootPath = (IPath)this.sourceAttachments.get(res.getFullPath());
// if (rootPath != null) {
// RootInfo rootInfo = this.rootInfo(rootPath, delta.getKind());
// if (rootInfo != null) {
// IJavaProject projectOfRoot = rootInfo.project;
// IPackageFragmentRoot root = null;
// try {
// // close the root so that source attachement cache is flushed
// root = projectOfRoot.findPackageFragmentRoot(rootPath);
// if (root != null) {
// root.close();
// }
// } catch (JavaModelException e) {
// }
// if (root == null) return;
// switch (delta.getKind()) {
// case IResourceDelta.ADDED:
// currentDelta().sourceAttached(root);
// break;
// case IResourceDelta.CHANGED:
// currentDelta().sourceDetached(root);
// currentDelta().sourceAttached(root);
// break;
// case IResourceDelta.REMOVED:
// currentDelta().sourceDetached(root);
// break;
// }
// }
// }
// }
/**
* Closes the given element, which removes it from the cache of open
* elements.
*/
// protected static void close(Openable element) {
//
// try {
// element.close();
// } catch (JavaModelException e) {
// // do nothing
// }
// }
/**
* Generic processing for elements with changed contents:
*
* - The element is closed such that any subsequent accesses will re-open
* the element reflecting its new structure.
*
- An entry is made in the delta reporting a content change (K_CHANGE
* with F_CONTENT flag set).
*
* Delta argument could be null if processing an external JAR change
*/
// protected void contentChanged(Openable element, IResourceDelta delta) {
//
// close(element);
// int flags = IJavaElementDelta.F_CONTENT;
// if (element instanceof JarPackageFragmentRoot){
// flags |= IJavaElementDelta.F_ARCHIVE_CONTENT_CHANGED;
// }
// currentDelta().changed(element, flags);
// }
//
/**
* Creates the openables corresponding to this resource. Returns null if
* none was found.
*/
// protected Openable createElement(IResource resource, int elementType,
// RootInfo rootInfo) {
// if (resource == null) return null;
//
// IPath path = resource.getFullPath();
// IJavaElement element = null;
// switch (elementType) {
//
// case IJavaElement.JAVA_PROJECT:
//
// // note that non-java resources rooted at the project level will also
// enter this code with
// // an elementType JAVA_PROJECT (see #elementType(...)).
// if (resource instanceof IProject){
//
// this.popUntilPrefixOf(path);
//
// if (this.currentElement != null
// && this.currentElement.getElementType() == IJavaElement.JAVA_PROJECT
// && ((IJavaProject)this.currentElement).getProject().equals(resource)) {
// return this.currentElement;
// }
// if (rootInfo != null && rootInfo.project.getProject().equals(resource)){
// element = (Openable)rootInfo.project;
// break;
// }
// IProject proj = (IProject)resource;
// if (JavaProject.hasJavaNature(proj)) {
// element = JavaCore.create(proj);
// } else {
// // java project may have been been closed or removed (look for
// // element amongst old java project s list).
// element = (Openable) manager.getJavaModel().findJavaProject(proj);
// }
// }
// break;
// case IJavaElement.PACKAGE_FRAGMENT_ROOT:
// element = rootInfo == null ? JavaCore.create(resource) :
// rootInfo.project.getPackageFragmentRoot(resource);
// break;
// case IJavaElement.PACKAGE_FRAGMENT:
// // find the element that encloses the resource
// this.popUntilPrefixOf(path);
//
// if (this.currentElement == null) {
// element = rootInfo == null ? JavaCore.create(resource) :
// JavaModelManager.create(resource, rootInfo.project);
// } else {
// // find the root
// IPackageFragmentRoot root = this.currentElement.getPackageFragmentRoot();
// if (root == null) {
// element = rootInfo == null ? JavaCore.create(resource) :
// JavaModelManager.create(resource, rootInfo.project);
// } else if (((JavaProject)root.getJavaProject()).contains(resource)) {
// // create package handle
// IPath pkgPath = path.removeFirstSegments(root.getPath().segmentCount());
// String pkg = ProjectPrefUtil.packageName(pkgPath);
// if (pkg == null) return null;
// element = root.getPackageFragment(pkg);
// }
// }
// break;
// case IJavaElement.COMPILATION_UNIT:
// case IJavaElement.CLASS_FILE:
// // find the element that encloses the resource
// this.popUntilPrefixOf(path);
//
// if (this.currentElement == null) {
// element = rootInfo == null ? JavaCore.create(resource) :
// JavaModelManager.create(resource, rootInfo.project);
// } else {
// // find the package
// IPackageFragment pkgFragment = null;
// switch (this.currentElement.getElementType()) {
// case IJavaElement.PACKAGE_FRAGMENT_ROOT:
// IPackageFragmentRoot root = (IPackageFragmentRoot)this.currentElement;
// IPath rootPath = root.getPath();
// IPath pkgPath = path.removeLastSegments(1);
// String pkgName =
// ProjectPrefUtil.packageName(pkgPath.removeFirstSegments(rootPath.segmentCount()));
// if (pkgName != null) {
// pkgFragment = root.getPackageFragment(pkgName);
// }
// break;
// case IJavaElement.PACKAGE_FRAGMENT:
// Openable pkg = (Openable)this.currentElement;
// if (pkg.getPath().equals(path.removeLastSegments(1))) {
// pkgFragment = (IPackageFragment)pkg;
// } // else case of package x which is a prefix of x.y
// break;
// case IJavaElement.COMPILATION_UNIT:
// case IJavaElement.CLASS_FILE:
// pkgFragment = (IPackageFragment)this.currentElement.getParent();
// break;
// }
// if (pkgFragment == null) {
// element = rootInfo == null ? JavaCore.create(resource) :
// JavaModelManager.create(resource, rootInfo.project);
// } else {
// if (elementType == IJavaElement.COMPILATION_UNIT) {
// // create compilation unit handle
// // fileName validation has been done in elementType(IResourceDelta, int,
// boolean)
// String fileName = path.lastSegment();
// element = pkgFragment.getCompilationUnit(fileName);
// } else {
// // create class file handle
// // fileName validation has been done in elementType(IResourceDelta, int,
// boolean)
// String fileName = path.lastSegment();
// element = pkgFragment.getClassFile(fileName);
// }
// }
// }
// break;
// }
// if (element == null) {
// return null;
// } else {
// this.currentElement = (Openable)element;
// return this.currentElement;
// }
// }
/**
* Note that the project is about to be deleted.
*/
// public void deleting(IProject project) {
//
// try {
// // discard indexing jobs that belong to this project so that the project
// can be
// // deleted without interferences from the index manager
// this.indexManager.discardJobs(project.getName());
//
// JavaProject javaProject = (JavaProject)JavaCore.create(project);
//
// // remember roots of this project
// if (this.removedRoots == null) {
// this.removedRoots = new HashMap();
// }
// if (javaProject.isOpen()) {
// this.removedRoots.put(javaProject,
// javaProject.getPackageFragmentRoots());
// } else {
// // compute roots without opening project
// this.removedRoots.put(
// javaProject,
// javaProject.computePackageFragmentRoots(
// javaProject.getResolvedClasspath(true),
// false));
// }
//
// javaProject.close();
//
// // workaround for bug 15168 circular errors not reported
// if (this.manager.javaProjectsCache == null) {
// this.manager.javaProjectsCache =
// this.manager.getJavaModel().getJavaProjects();
// }
// this.removeFromParentInfo(javaProject);
//
// } catch (JavaModelException e) {
// }
//
// this.addDependentProjects(project.getFullPath(), this.projectsToUpdate);
// }
/**
* Processing for an element that has been added:
*
* - If the element is a project, do nothing, and do not process
* children, as when a project is created it does not yet have any natures -
* specifically a java nature.
*
- If the elemet is not a project, process it as added (see
*
basicElementAdded
.
*
* Delta argument could be null if processing an external JAR change
*/
// protected void elementAdded(Openable element, IResourceDelta delta,
// RootInfo rootInfo) {
// int elementType = element.getElementType();
//
// if (elementType == IJavaElement.JAVA_PROJECT) {
// // project add is handled by JavaProject.configure() because
// // when a project is created, it does not yet have a java nature
// if (delta != null &&
// JavaProject.hasJavaNature((IProject)delta.getResource())) {
// addToParentInfo(element);
// if ((delta.getFlags() & IResourceDelta.MOVED_FROM) != 0) {
// Openable movedFromElement =
// (Openable)element.getJavaModel().getJavaProject(delta.getMovedFromPath().lastSegment());
// currentDelta().movedTo(element, movedFromElement);
// } else {
// currentDelta().added(element);
// }
// this.projectsToUpdate.add(element);
// this.updateRoots(element.getPath(), delta);
// this.projectsForDependentNamelookupRefresh.add((JavaProject) element);
// }
// } else {
// addToParentInfo(element);
//
// // Force the element to be closed as it might have been opened
// // before the resource modification came in and it might have a new child
// // For example, in an IWorkspaceRunnable:
// // 1. create a package fragment p using a java model operation
// // 2. open package p
// // 3. add file X.java in folder p
// // When the resource delta comes in, only the addition of p is notified,
// // but the package p is already opened, thus its children are not
// recomputed
// // and it appears empty.
// close(element);
//
// if (delta != null && (delta.getFlags() & IResourceDelta.MOVED_FROM) != 0)
// {
// IPath movedFromPath = delta.getMovedFromPath();
// IResource res = delta.getResource();
// IResource movedFromRes;
// if (res instanceof IFile) {
// movedFromRes = res.getWorkspace().getRoot().getFile(movedFromPath);
// } else {
// movedFromRes = res.getWorkspace().getRoot().getFolder(movedFromPath);
// }
//
// // find the element type of the moved from element
// RootInfo movedFromInfo = this.enclosingRootInfo(movedFromPath,
// IResourceDelta.REMOVED);
// int movedFromType =
// this.elementType(
// movedFromRes,
// IResourceDelta.REMOVED,
// element.getParent().getElementType(),
// movedFromInfo);
//
// // reset current element as it might be inside a nested root
// (popUntilPrefixOf() may use the outer root)
// this.currentElement = null;
//
// // create the moved from element
// Openable movedFromElement =
// elementType != IJavaElement.JAVA_PROJECT && movedFromType ==
// IJavaElement.JAVA_PROJECT ?
// null : // outside classpath
// this.createElement(movedFromRes, movedFromType, movedFromInfo);
// if (movedFromElement == null) {
// // moved from outside classpath
// currentDelta().added(element);
// } else {
// currentDelta().movedTo(element, movedFromElement);
// }
// } else {
// currentDelta().added(element);
// }
//
// switch (elementType) {
// case IJavaElement.PACKAGE_FRAGMENT_ROOT :
// // when a root is added, and is on the classpath, the project must be
// updated
// JavaProject project = (JavaProject) element.getJavaProject();
// this.projectsToUpdate.add(project);
// this.projectsForDependentNamelookupRefresh.add(project);
//
// break;
// case IJavaElement.PACKAGE_FRAGMENT :
// // get rid of namelookup since it holds onto obsolete cached info
// project = (JavaProject) element.getJavaProject();
// try {
// project.getJavaProjectElementInfo().setNameLookup(null);
// this.projectsForDependentNamelookupRefresh.add(project);
// } catch (JavaModelException e) {
// }
// // add subpackages
// if (delta != null){
// PackageFragmentRoot root = element.getPackageFragmentRoot();
// String name = element.getElementName();
// IResourceDelta[] children = delta.getAffectedChildren();
// for (int i = 0, length = children.length; i < length; i++) {
// IResourceDelta child = children[i];
// IResource resource = child.getResource();
// if (resource instanceof IFolder) {
// String folderName = resource.getName();
// if (ProjectPrefUtil.isValidFolderNameForPackage(folderName)) {
// String subpkgName =
// name.length() == 0 ?
// folderName :
// name + "." + folderName; //$NON-NLS-1$
// Openable subpkg = (Openable)root.getPackageFragment(subpkgName);
// this.updateIndex(subpkg, child);
// this.elementAdded(subpkg, child, rootInfo);
// }
// }
// }
// }
// break;
// }
// }
// }
/**
* Generic processing for a removed element:
*
* - Close the element, removing its structure from the cache
*
- Remove the element from its parent's cache of children
*
- Add a REMOVED entry in the delta
*
* Delta argument could be null if processing an external JAR change
*/
// protected void elementRemoved(Openable element, IResourceDelta delta,
// RootInfo rootInfo) {
//
// if (element.isOpen()) {
// close(element);
// }
// removeFromParentInfo(element);
// int elementType = element.getElementType();
// if (delta != null && (delta.getFlags() & IResourceDelta.MOVED_TO) != 0) {
// IPath movedToPath = delta.getMovedToPath();
// IResource res = delta.getResource();
// IResource movedToRes;
// switch (res.getType()) {
// case IResource.PROJECT:
// movedToRes =
// res.getWorkspace().getRoot().getProject(movedToPath.lastSegment());
// break;
// case IResource.FOLDER:
// movedToRes = res.getWorkspace().getRoot().getFolder(movedToPath);
// break;
// case IResource.FILE:
// movedToRes = res.getWorkspace().getRoot().getFile(movedToPath);
// break;
// default:
// return;
// }
//
// // find the element type of the moved from element
// RootInfo movedToInfo = this.enclosingRootInfo(movedToPath,
// IResourceDelta.ADDED);
// int movedToType =
// this.elementType(
// movedToRes,
// IResourceDelta.ADDED,
// element.getParent().getElementType(),
// movedToInfo);
//
// // reset current element as it might be inside a nested root
// (popUntilPrefixOf() may use the outer root)
// this.currentElement = null;
//
// // create the moved To element
// Openable movedToElement =
// elementType != IJavaElement.JAVA_PROJECT && movedToType ==
// IJavaElement.JAVA_PROJECT ?
// null : // outside classpath
// this.createElement(movedToRes, movedToType, movedToInfo);
// if (movedToElement == null) {
// // moved outside classpath
// currentDelta().removed(element);
// } else {
// currentDelta().movedFrom(element, movedToElement);
// }
// } else {
// currentDelta().removed(element);
// }
//
// switch (elementType) {
// case IJavaElement.JAVA_MODEL :
// this.indexManager.reset();
// break;
// case IJavaElement.JAVA_PROJECT :
// this.manager.removePerProjectInfo(
// (JavaProject) element);
// this.updateRoots(element.getPath(), delta);
// this.projectsForDependentNamelookupRefresh.add((JavaProject) element);
// break;
// case IJavaElement.PACKAGE_FRAGMENT_ROOT :
// JavaProject project = (JavaProject) element.getJavaProject();
// this.projectsToUpdate.add(project);
// this.projectsForDependentNamelookupRefresh.add(project);
// break;
// case IJavaElement.PACKAGE_FRAGMENT :
// //1G1TW2T - get rid of namelookup since it holds onto obsolete cached
// info
// project = (JavaProject) element.getJavaProject();
// try {
// project.getJavaProjectElementInfo().setNameLookup(null);
// this.projectsForDependentNamelookupRefresh.add(project);
// } catch (JavaModelException e) {
// }
// // remove subpackages
// if (delta != null){
// PackageFragmentRoot root = element.getPackageFragmentRoot();
// String name = element.getElementName();
// IResourceDelta[] children = delta.getAffectedChildren();
// for (int i = 0, length = children.length; i < length; i++) {
// IResourceDelta child = children[i];
// IResource resource = child.getResource();
// if (resource instanceof IFolder) {
// String folderName = resource.getName();
// if (ProjectPrefUtil.isValidFolderNameForPackage(folderName)) {
// String subpkgName =
// name.length() == 0 ?
// folderName :
// name + "." + folderName; //$NON-NLS-1$
// Openable subpkg = (Openable)root.getPackageFragment(subpkgName);
// this.updateIndex(subpkg, child);
// this.elementRemoved(subpkg, child, rootInfo);
// }
// }
// }
// }
// break;
// }
// }
/*
* Returns the type of the java element the given delta matches to. Returns
* NON_JAVA_RESOURCE if unknown (e.g. a non-java resource or excluded .java
* file)
*/
// private int elementType(IResource res, int kind, int parentType, RootInfo
// rootInfo) {
// switch (parentType) {
// case IJavaElement.JAVA_MODEL:
// // case of a movedTo or movedFrom project (other cases are handled in
// processResourceDelta(...)
// return IJavaElement.JAVA_PROJECT;
// case NON_JAVA_RESOURCE:
// case IJavaElement.JAVA_PROJECT:
// if (rootInfo == null) {
// rootInfo = this.enclosingRootInfo(res.getFullPath(), kind);
// }
// if (rootInfo != null && rootInfo.isRootOfProject(res.getFullPath())) {
// return IJavaElement.PACKAGE_FRAGMENT_ROOT;
// } else {
// return NON_JAVA_RESOURCE; // not yet in a package fragment root or root
// of another project
// }
// case IJavaElement.PACKAGE_FRAGMENT_ROOT:
// case IJavaElement.PACKAGE_FRAGMENT:
// if (rootInfo == null) {
// rootInfo = this.enclosingRootInfo(res.getFullPath(), kind);
// }
// if (rootInfo == null || ProjectPrefUtil.isExcluded(res,
// rootInfo.exclusionPatterns)) {
// return NON_JAVA_RESOURCE;
// }
// if (res instanceof IFolder) {
// if (ProjectPrefUtil.isValidFolderNameForPackage(res.getName())) {
// return IJavaElement.PACKAGE_FRAGMENT;
// } else {
// return NON_JAVA_RESOURCE;
// }
// } else {
// String fileName = res.getName();
// if (ProjectPrefUtil.isValidCompilationUnitName(fileName)) {
// return IJavaElement.COMPILATION_UNIT;
// } else if (ProjectPrefUtil.isValidClassFileName(fileName)) {
// return IJavaElement.CLASS_FILE;
// } else if (this.rootInfo(res.getFullPath(), kind) != null) {
// // case of proj=src=bin and resource is a jar file on the classpath
// return IJavaElement.PACKAGE_FRAGMENT_ROOT;
// } else {
// return NON_JAVA_RESOURCE;
// }
// }
// default:
// return NON_JAVA_RESOURCE;
// }
// }
/**
* Answer a combination of the lastModified stamp and the size. Used for
* detecting external JAR changes
*/
// public static long getTimeStamp(File file) {
// return file.lastModified() + file.length();
// }
// public void initializeRoots() {
// // remember roots infos as old roots infos
// this.oldRoots = this.roots == null ? new HashMap() : this.roots;
// this.oldOtherRoots = this.otherRoots == null ? new HashMap()
// : this.otherRoots;
//
// // recompute root infos only if necessary
// if (!rootsAreStale)
// return;
//
// this.roots = new HashMap();
// this.otherRoots = new HashMap();
// this.sourceAttachments = new HashMap();
//
// IJavaModel model = this.manager.getJavaModel();
// IJavaProject[] projects;
// try {
// projects = model.getJavaProjects();
// } catch (JavaModelException e) {
// // nothing can be done
// return;
// }
// for (int i = 0, length = projects.length; i < length; i++) {
// IJavaProject project = projects[i];
// IClasspathEntry[] classpath;
// try {
// classpath = project.getResolvedClasspath(true);
// } catch (JavaModelException e) {
// // continue with next project
// continue;
// }
// for (int j = 0, classpathLength = classpath.length; j < classpathLength; j++) {
// IClasspathEntry entry = classpath[j];
// if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT)
// continue;
//
// // root path
// IPath path = entry.getPath();
// if (this.roots.get(path) == null) {
// this.roots.put(path, new RootInfo(project, path,
// ((ClasspathEntry) entry)
// .fullExclusionPatternChars()));
// } else {
// ArrayList rootList = (ArrayList) this.otherRoots.get(path);
// if (rootList == null) {
// rootList = new ArrayList();
// this.otherRoots.put(path, rootList);
// }
// rootList.add(new RootInfo(project, path,
// ((ClasspathEntry) entry)
// .fullExclusionPatternChars()));
// }
//
// // source attachment path
// if (entry.getEntryKind() != IClasspathEntry.CPE_LIBRARY)
// continue;
// QualifiedName qName = new QualifiedName(JavaCore.PLUGIN_ID,
// "sourceattachment: " + path.toOSString()); //$NON-NLS-1$;
// String propertyString = null;
// try {
// propertyString = ResourcesPlugin.getWorkspace().getRoot()
// .getPersistentProperty(qName);
// } catch (CoreException e) {
// continue;
// }
// IPath sourceAttachmentPath;
// // if (propertyString != null) {
// // int index=
// // propertyString.lastIndexOf(JarPackageFragmentRoot.ATTACHMENT_PROPERTY_DELIMITER);
// // sourceAttachmentPath = (index < 0) ? new Path(propertyString)
// // : new Path(propertyString.substring(0, index));
// // } else {
// sourceAttachmentPath = entry.getSourceAttachmentPath();
// // }
// if (sourceAttachmentPath != null) {
// this.sourceAttachments.put(sourceAttachmentPath, path);
// }
// }
// }
// this.rootsAreStale = false;
// }
/*
* Returns whether a given delta contains some information relevant to the
* JavaModel, in particular it will not consider SYNC or MARKER only deltas.
*/
public boolean isAffectedBy(IResourceDelta rootDelta) {
// if (rootDelta == null) System.out.println("NULL DELTA");
// long start = System.currentTimeMillis();
if (rootDelta != null) {
// use local exception to quickly escape from delta traversal
class FoundRelevantDeltaException extends RuntimeException {
/**
*
*/
private static final long serialVersionUID = -7732598607464929404L;
}
try {
rootDelta.accept(new IResourceDeltaVisitor() {
public boolean visit(IResourceDelta delta)
throws CoreException {
switch (delta.getKind()) {
case IResourceDelta.ADDED:
case IResourceDelta.REMOVED:
throw new FoundRelevantDeltaException();
case IResourceDelta.CHANGED:
// if any flag is set but SYNC or MARKER, this delta
// should be considered
if (delta.getAffectedChildren().length == 0 // only
// check
// leaf
// delta
// nodes
&& (delta.getFlags() & ~(IResourceDelta.SYNC | IResourceDelta.MARKERS)) != 0) {
throw new FoundRelevantDeltaException();
}
}
return true;
}
});
} catch (FoundRelevantDeltaException e) {
// System.out.println("RELEVANT DELTA detected in: "+
// (System.currentTimeMillis() - start));
return true;
} catch (CoreException e) { // ignore delta if not able to traverse
}
}
// System.out.println("IGNORE SYNC DELTA took: "+
// (System.currentTimeMillis() - start));
return false;
}
/*
* Returns whether the given resource is in one of the given output folders
* and if it is filtered out from this output folder.
*/
// private boolean isResFilteredFromOutput(OutputsInfo info, IResource res,
// int elementType) {
// if (info != null) {
// IPath resPath = res.getFullPath();
// for (int i = 0; i < info.outputCount; i++) {
// if (info.paths[i].isPrefixOf(resPath)) {
// if (info.traverseModes[i] != IGNORE) {
// // case of bin=src
// if (info.traverseModes[i] == SOURCE
// && elementType == IJavaElement.CLASS_FILE) {
// return true;
// } else {
// // case of .class file under project and no source
// // folder
// // proj=bin
// if (elementType == IJavaElement.JAVA_PROJECT
// && res instanceof IFile
// && PHPFileUtil.isPHPFile((IFile) res)) {
// return true;
// }
// }
// } else {
// return true;
// }
// }
// }
// }
// return false;
// }
/*
* Merges all awaiting deltas.
*/
private IJavaElementDelta mergeDeltas(Collection deltas) {
if (deltas.size() == 0)
return null;
if (deltas.size() == 1)
return (IJavaElementDelta) deltas.iterator().next();
if (VERBOSE) {
System.out
.println("MERGING " + deltas.size() + " DELTAS [" + Thread.currentThread() + "]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
Iterator iterator = deltas.iterator();
JavaElementDelta rootDelta = new JavaElementDelta(
this.manager.javaModel);
boolean insertedTree = false;
while (iterator.hasNext()) {
JavaElementDelta delta = (JavaElementDelta) iterator.next();
if (VERBOSE) {
System.out.println(delta.toString());
}
IJavaElement element = delta.getElement();
if (this.manager.javaModel.equals(element)) {
IJavaElementDelta[] children = delta.getAffectedChildren();
for (int j = 0; j < children.length; j++) {
JavaElementDelta projectDelta = (JavaElementDelta) children[j];
rootDelta.insertDeltaTree(projectDelta.getElement(),
projectDelta);
insertedTree = true;
}
IResourceDelta[] resourceDeltas = delta.getResourceDeltas();
if (resourceDeltas != null) {
for (int i = 0, length = resourceDeltas.length; i < length; i++) {
rootDelta.addResourceDelta(resourceDeltas[i]);
insertedTree = true;
}
}
} else {
rootDelta.insertDeltaTree(element, delta);
insertedTree = true;
}
}
if (insertedTree)
return rootDelta;
return null;
}
/**
* Check whether the updated file is affecting some of the properties of a
* given project (like its classpath persisted as a file). Also force
* classpath problems to be refresh if not running in autobuild mode. NOTE:
* It can induce resource changes, and cannot be called during POST_CHANGE
* notification.
*
*/
// public void performPreBuildCheck(
// IResourceDelta delta,
// IJavaElement parent) {
//
// IResource resource = delta.getResource();
// IJavaElement element = null;
// boolean processChildren = false;
//
// switch (resource.getType()) {
//
// case IResource.ROOT :
// if (delta.getKind() == IResourceDelta.CHANGED) {
// element = JavaCore.create(resource);
// processChildren = true;
// }
// break;
// case IResource.PROJECT :
// int kind = delta.getKind();
// switch (kind) {
// case IResourceDelta.CHANGED:
// // do not visit non-java projects (see bug 16140 Non-java project gets
// .classpath)
// IProject project = (IProject)resource;
// if (JavaProject.hasJavaNature(project)) {
// element = JavaCore.create(resource);
// processChildren = true;
// } else if
// (JavaModelManager.getJavaModelManager().getJavaModel().findJavaProject(project)
// != null) {
// // project had the java nature
// this.rootsAreStale = true;
//
// // remove classpath cache so that initializeRoots() will not consider the
// project has a classpath
// this.manager.removePerProjectInfo((JavaProject)JavaCore.create(project));
// }
// break;
// case IResourceDelta.ADDED:
// this.rootsAreStale = true;
// break;
// case IResourceDelta.REMOVED:
// // remove classpath cache so that initializeRoots() will not consider the
// project has a classpath
// this.manager.removePerProjectInfo((JavaProject)JavaCore.create(resource));
//
// this.rootsAreStale = true;
// break;
// }
// break;
// case IResource.FILE :
// if (parent.getElementType() == IJavaElement.JAVA_PROJECT) {
// IFile file = (IFile) resource;
// JavaProject project = (JavaProject) parent;
//
// /* check classpath file change */
// if (file.getName().equals(JavaProject.CLASSPATH_FILENAME)) {
// reconcileClasspathFileUpdate(delta, file, project);
// this.rootsAreStale = true;
// break;
// }
// // /* check custom preference file change */
// // if (file.getName().equals(JavaProject.PREF_FILENAME)) {
// // reconcilePreferenceFileUpdate(delta, file, project);
// // break;
// // }
// }
// break;
// }
// if (processChildren) {
// IResourceDelta[] children = delta.getAffectedChildren();
// for (int i = 0; i < children.length; i++) {
// performPreBuildCheck(children[i], element);
// }
// }
// }
// private void popUntilPrefixOf(IPath path) {
// while (this.currentElement != null) {
// IPath currentElementPath = null;
// if (this.currentElement instanceof IPackageFragmentRoot) {
// currentElementPath =
// ((IPackageFragmentRoot)this.currentElement).getPath();
// } else {
// IResource currentElementResource = this.currentElement.getResource();
// if (currentElementResource != null) {
// currentElementPath = currentElementResource.getFullPath();
// }
// }
// if (currentElementPath != null) {
// if (this.currentElement instanceof IPackageFragment
// && this.currentElement.getElementName().length() == 0
// && currentElementPath.segmentCount() != path.segmentCount()-1) {
// // default package and path is not a direct child
// this.currentElement = (Openable)this.currentElement.getParent();
// }
// if (currentElementPath.isPrefixOf(path)) {
// return;
// }
// }
// this.currentElement = (Openable)this.currentElement.getParent();
// }
// }
/**
* Converts a IResourceDelta
rooted in a
* Workspace
into the corresponding set of
* IJavaElementDelta
, rooted in the relevant
* JavaModel
s.
*/
/**
* Update the JavaModel according to a .classpath file change. The file can
* have changed as a result of a previous call to
* JavaProject#setRawClasspath or as a result of some user update (through
* repository)
*/
// void reconcileClasspathFileUpdate(IResourceDelta delta, IFile file,
// JavaProject project) {
//
// switch (delta.getKind()) {
// case IResourceDelta.REMOVED : // recreate one based on in-memory
// classpath
// try {
// JavaModelManager.PerProjectInfo info =
// JavaModelManager.getJavaModelManager().getPerProjectInfoCheckExistence(project.getProject());
// if (info.classpath != null) { // if there is an in-memory classpath
// project.saveClasspath(info.classpath, info.outputLocation);
// }
// } catch (JavaModelException e) {
// if (project.getProject().isAccessible()) {
// ProjectPrefUtil.log(e, "Could not save classpath for "+
// project.getPath()); //$NON-NLS-1$
// }
// }
// break;
// case IResourceDelta.CHANGED :
// if ((delta.getFlags() & IResourceDelta.CONTENT) == 0 // only consider
// content change
// && (delta.getFlags() & IResourceDelta.MOVED_FROM) == 0) // and also move
// and overide scenario (see
// http://dev.eclipse.org/bugs/show_bug.cgi?id=21420)
// break;
// case IResourceDelta.ADDED :
// // check if any actual difference
// project.flushClasspathProblemMarkers(false, true);
// boolean wasSuccessful = false; // flag recording if .classpath file
// change got reflected
// try {
// // force to (re)read the property file
// IClasspathEntry[] fileEntries = project.readClasspathFile(true/*create
// markers*/, false/*don't log problems*/);
// if (fileEntries == null)
// break; // could not read, ignore
// JavaModelManager.PerProjectInfo info =
// JavaModelManager.getJavaModelManager().getPerProjectInfoCheckExistence(project.getProject());
// if (info.classpath != null) { // if there is an in-memory classpath
// if (project.isClasspathEqualsTo(info.classpath, info.outputLocation,
// fileEntries)) {
// wasSuccessful = true;
// break;
// }
// }
//
// // will force an update of the classpath/output location based on the
// file information
// // extract out the output location
// IPath outputLocation = null;
// if (fileEntries != null && fileEntries.length > 0) {
// IClasspathEntry entry = fileEntries[fileEntries.length - 1];
// if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) {
// outputLocation = entry.getPath();
// IClasspathEntry[] copy = new IClasspathEntry[fileEntries.length - 1];
// System.arraycopy(fileEntries, 0, copy, 0, copy.length);
// fileEntries = copy;
// }
// }
// // restore output location
// if (outputLocation == null) {
// outputLocation = SetClasspathOperation.ReuseOutputLocation;
// // clean mode will also default to reusing current one
// }
// project.setRawClasspath(
// fileEntries,
// outputLocation,
// null, // monitor
// true, // canChangeResource
// project.getResolvedClasspath(true), // ignoreUnresolvedVariable
// true, // needValidation
// false); // no need to save
//
// // if reach that far, the classpath file change got absorbed
// wasSuccessful = true;
// } catch (RuntimeException e) {
// // setRawClasspath might fire a delta, and a listener may throw an
// exception
// if (project.getProject().isAccessible()) {
// ProjectPrefUtil.log(e, "Could not set classpath for "+
// project.getPath()); //$NON-NLS-1$
// }
// break;
// } catch (JavaModelException e) { // CP failed validation
// if (project.getProject().isAccessible()) {
// if (e.getJavaModelStatus().getException() instanceof CoreException) {
// // happens if the .classpath could not be written to disk
// project.createClasspathProblemMarker(new JavaModelStatus(
// IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
// ProjectPrefUtil.bind("classpath.couldNotWriteClasspathFile",
// project.getElementName(), e.getMessage()))); //$NON-NLS-1$
// } else {
// project.createClasspathProblemMarker(new JavaModelStatus(
// IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
// ProjectPrefUtil.bind("classpath.invalidClasspathInClasspathFile",
// project.getElementName(), e.getMessage()))); //$NON-NLS-1$
// }
// }
// break;
// } finally {
// if (!wasSuccessful) {
// try {
// project.setRawClasspath0(JavaProject.INVALID_CLASSPATH);
// project.updatePackageFragmentRoots();
// } catch (JavaModelException e) {
// }
// }
// }
// }
// }
/**
* Update the JavaModel according to a .jprefs file change. The file can
* have changed as a result of a previous call to JavaProject#setOptions or
* as a result of some user update (through repository) Unused until
* preference file get shared (.jpref)
*/
// void reconcilePreferenceFileUpdate(IResourceDelta delta, IFile file,
// JavaProject project) {
//
// switch (delta.getKind()) {
// case IResourceDelta.REMOVED : // flush project custom settings
// project.setOptions(null);
// return;
// case IResourceDelta.CHANGED :
// if ((delta.getFlags() & IResourceDelta.CONTENT) == 0 // only consider
// content change
// && (delta.getFlags() & IResourceDelta.MOVED_FROM) == 0) // and also move
// and overide scenario
// break;
// identityCheck : { // check if any actual difference
// // force to (re)read the property file
// Preferences filePreferences = project.loadPreferences();
// if (filePreferences == null){
// project.setOptions(null); // should have got removed delta.
// return;
// }
// Preferences projectPreferences = project.getPreferences();
// if (projectPreferences == null) return; // not a Java project
//
// // compare preferences set to their default
// String[] defaultProjectPropertyNames =
// projectPreferences.defaultPropertyNames();
// String[] defaultFilePropertyNames =
// filePreferences.defaultPropertyNames();
// if (defaultProjectPropertyNames.length ==
// defaultFilePropertyNames.length) {
// for (int i = 0; i < defaultProjectPropertyNames.length; i++){
// String propertyName = defaultProjectPropertyNames[i];
// if
// (!projectPreferences.getString(propertyName).trim().equals(filePreferences.getString(propertyName).trim())){
// break identityCheck;
// }
// }
// } else break identityCheck;
//
// // compare custom preferences not set to their default
// String[] projectPropertyNames = projectPreferences.propertyNames();
// String[] filePropertyNames = filePreferences.propertyNames();
// if (projectPropertyNames.length == filePropertyNames.length) {
// for (int i = 0; i < projectPropertyNames.length; i++){
// String propertyName = projectPropertyNames[i];
// if
// (!projectPreferences.getString(propertyName).trim().equals(filePreferences.getString(propertyName).trim())){
// break identityCheck;
// }
// }
// } else break identityCheck;
//
// // identical - do nothing
// return;
// }
// case IResourceDelta.ADDED :
// // not identical, create delta and reset cached preferences
// project.setPreferences(null);
// // create delta
// //fCurrentDelta.changed(project, IJavaElementDelta.F_OPTIONS_CHANGED);
// }
// }
/*
* Registers the given delta with this delta processor.
*/
public void registerJavaModelDelta(IJavaElementDelta delta) {
this.javaModelDeltas.add(delta);
}
/**
* Removes the given element from its parents cache of children. If the
* element does not have a parent, or the parent is not currently open, this
* has no effect.
*/
protected void removeFromParentInfo(Openable child) {
Openable parent = (Openable) child.getParent();
if (parent != null && parent.isOpen()) {
try {
JavaElementInfo info = (JavaElementInfo) parent
.getElementInfo();
info.removeChild(child);
} catch (JavaModelException e) {
// do nothing - we already checked if open
}
}
}
/**
* Notification that some resource changes have happened on the platform,
* and that the Java Model should update any required internal structures
* such that its elements remain consistent. Translates
* IResourceDeltas
into IJavaElementDeltas
.
*
* @see IResourceDelta
* @see IResource
*/
public void resourceChanged(IResourceChangeEvent event) {
if (event.getSource() instanceof IWorkspace) {
int eventType = this.overridenEventType == -1 ? event.getType()
: this.overridenEventType;
IResource resource = event.getResource();
IResourceDelta delta = event.getDelta();
switch (eventType) {
case IResourceChangeEvent.PRE_DELETE:
try {
if (resource.getType() == IResource.PROJECT
&& ((IProject) resource)
.hasNature(PHPeclipsePlugin.PHP_NATURE_ID)) {
deleting((IProject) resource);
}
} catch (CoreException e) {
// project doesn't exist or is not open: ignore
}
return;
case IResourceChangeEvent.POST_CHANGE:
if (isAffectedBy(delta)) { // avoid populating for SYNC or
// MARKER deltas
try {
try {
stopDeltas();
// checkProjectsBeingAddedOrRemoved(delta);
// if (this.refreshedElements != null) {
// createExternalArchiveDelta(null);
// }
IJavaElementDelta translatedDelta = processResourceDelta(delta);
if (translatedDelta != null) {
registerJavaModelDelta(translatedDelta);
}
} finally {
startDeltas();
}
// notifyTypeHierarchies(this.state.elementChangedListeners,
// this.state.elementChangedListenerCount);
fire(null, ElementChangedEvent.POST_CHANGE);
} finally {
// workaround for bug 15168 circular errors not reported
this.state.modelProjectsCache = null;
this.removedRoots = null;
}
}
return;
case IResourceChangeEvent.PRE_BUILD:
DeltaProcessingState.ProjectUpdateInfo[] updates = this.state
.removeAllProjectUpdates();
if (updates != null) {
for (int i = 0, length = updates.length; i < length; i++) {
try {
updates[i].updateProjectReferencesIfNecessary();
} catch (JavaModelException e) {
// do nothing
}
}
}
// this.processPostChange = false;
if (isAffectedBy(delta)) { // avoid populating for SYNC or
// MARKER deltas
// updateClasspathMarkers(delta);
PHPBuilder.buildStarting();
}
// does not fire any deltas
return;
case IResourceChangeEvent.POST_BUILD:
PHPBuilder.buildFinished();
return;
}
}
// // jsurfer TODO compare 3.0 sources
// if (event.getSource() instanceof IWorkspace) {
// int eventType = this.overridenEventType == -1 ? event.getType() :
// this.overridenEventType;
// IResource resource = event.getResource();
// IResourceDelta delta = event.getDelta();
//
// switch(eventType){
// case IResourceChangeEvent.PRE_DELETE :
// try {
// if(resource.getType() == IResource.PROJECT
// && ((IProject) resource).hasNature(PHPeclipsePlugin.PHP_NATURE_ID)) {
// // TODO jsurfer temp-del
// // this.deleting((IProject)resource);
// }
// } catch(CoreException e){
// }
// return;
//
// case IResourceChangeEvent.PRE_BUILD :
// // TODO jsurfer temp-del
// // if(isAffectedBy(delta)) { // avoid populating for SYNC or MARKER
// deltas
// // this.checkProjectsBeingAddedOrRemoved(delta);
// //
// // // update the classpath related markers
// // this.updateClasspathMarkers();
// //
// // // the following will close project if affected by the property
// file change
// // try {
// // // don't fire classpath change deltas right away, but batch them
// // this.manager.stopDeltas();
// // this.performPreBuildCheck(delta, null);
// // } finally {
// // this.manager.startDeltas();
// // }
// // }
// // only fire already computed deltas (resource ones will be processed
// in post change only)
// this.manager.fire(null, ElementChangedEvent.PRE_AUTO_BUILD);
// break;
//
// case IResourceChangeEvent.POST_BUILD :
// // TODO jsurfer temp-del
// // JavaBuilder.finishedBuilding(event);
// break;
//
// case IResourceChangeEvent.POST_CHANGE :
// // TODO jsurfer temp-del
// // if (isAffectedBy(delta)) {
// // try {
// // if (this.refreshedElements != null) {
// // try {
// // createExternalArchiveDelta(null);
// // } catch (JavaModelException e) {
// // e.printStackTrace();
// // }
// // }
// // IJavaElementDelta translatedDelta =
// this.processResourceDelta(delta);
// // if (translatedDelta != null) {
// // this.manager.registerJavaModelDelta(translatedDelta);
// // }
// // this.manager.fire(null, ElementChangedEvent.POST_CHANGE);
// // } finally {
// // // workaround for bug 15168 circular errors not reported
// // this.manager.javaProjectsCache = null;
// // this.removedRoots = null;
// // }
// // }
// }
// }
}
/*
* Turns the firing mode to on. That is, deltas that are/have been
* registered will be fired.
*/
private void startDeltas() {
this.isFiring = true;
}
/*
* Turns the firing mode to off. That is, deltas that are/have been
* registered will not be fired until deltas are started again.
*/
private void stopDeltas() {
this.isFiring = false;
}
/*
* Note that the project is about to be deleted.
*/
private void deleting(IProject project) {
try {
// discard indexing jobs that belong to this project so that the
// project can be
// deleted without interferences from the index manager
// this.manager.indexManager.discardJobs(project.getName());
JavaProject javaProject = (JavaProject) JavaCore.create(project);
// remember roots of this project
if (this.removedRoots == null) {
this.removedRoots = new HashMap();
}
if (javaProject.isOpen()) {
this.removedRoots.put(javaProject, javaProject
.getPackageFragmentRoots());
} else {
// compute roots without opening project
// this.removedRoots.put(
// javaProject,
// javaProject.computePackageFragmentRoots(
// javaProject.getResolvedClasspath(true/*ignoreUnresolvedEntry*/,
// false/*don't generateMarkerOnError*/, false/*don't
// returnResolutionInProgress*/),
// false));
}
javaProject.close();
// workaround for bug 15168 circular errors not reported
if (this.state.modelProjectsCache == null) {
this.state.modelProjectsCache = this.manager.getJavaModel()
.getJavaProjects();
}
this.removeFromParentInfo(javaProject);
} catch (JavaModelException e) {
// java project doesn't exist: ignore
}
}
/*
* Converts a IResourceDelta
rooted in a Workspace
* into the corresponding set of IJavaElementDelta
, rooted
* in the relevant JavaModel
s.
*/
private IJavaElementDelta processResourceDelta(IResourceDelta changes) {
try {
IJavaModel model = this.manager.getJavaModel();
if (!model.isOpen()) {
// force opening of java model so that java element delta are
// reported
try {
model.open(null);
} catch (JavaModelException e) {
if (VERBOSE) {
e.printStackTrace();
}
return null;
}
}
this.state.initializeRoots();
this.currentElement = null;
// get the workspace delta, and start processing there.
IResourceDelta[] deltas = changes.getAffectedChildren();
for (int i = 0; i < deltas.length; i++) {
IResourceDelta delta = deltas[i];
IResource res = delta.getResource();
// find out the element type
// RootInfo rootInfo = null;
int elementType;
IProject proj = (IProject) res;
boolean wasJavaProject = this.manager.getJavaModel()
.findJavaProject(proj) != null;
boolean isJavaProject = JavaProject.hasJavaNature(proj);
if (!wasJavaProject && !isJavaProject) {
elementType = NON_JAVA_RESOURCE;
} else {
// rootInfo = this.enclosingRootInfo(res.getFullPath(),
// delta.getKind());
// if (rootInfo != null &&
// rootInfo.isRootOfProject(res.getFullPath())) {
// elementType = IJavaElement.PACKAGE_FRAGMENT_ROOT;
// } else {
elementType = IJavaElement.JAVA_PROJECT;
// }
}
// traverse delta
// this.traverseDelta(delta, elementType, rootInfo, null);
if (elementType == NON_JAVA_RESOURCE
|| (wasJavaProject != isJavaProject && (delta.getKind()) == IResourceDelta.CHANGED)) { // project
// has
// changed
// nature
// (description
// or
// open/closed)
try {
// add child as non java resource
nonJavaResourcesChanged((JavaModel) model, delta);
} catch (JavaModelException e) {
// java model could not be opened
}
}
}
// refreshPackageFragmentRoots();
// resetProjectCaches();
return this.currentDelta;
} finally {
this.currentDelta = null;
// this.rootsToRefresh.clear();
// this.projectCachesToReset.clear();
}
}
/*
* Converts an IResourceDelta
and its children into the
* corresponding IJavaElementDelta
s.
*/
// private void traverseDelta(
// IResourceDelta delta,
// int elementType,
// RootInfo rootInfo,
// OutputsInfo outputsInfo) {
//
// IResource res = delta.getResource();
//
// // set stack of elements
// if (this.currentElement == null && rootInfo != null) {
// // this.currentElement = rootInfo.project;
// }
//
// // process current delta
// boolean processChildren = true;
// if (res instanceof IProject) {
// processChildren =
// this.updateCurrentDeltaAndIndex(
// delta,
// elementType == IJavaElement.PACKAGE_FRAGMENT_ROOT ?
// IJavaElement.JAVA_PROJECT : // case of prj=src
// elementType,
// rootInfo);
// } else if (rootInfo != null) {
// processChildren = this.updateCurrentDeltaAndIndex(delta, elementType,
// rootInfo);
// } else {
// // not yet inside a package fragment root
// processChildren = true;
// }
//
// // get the project's output locations and traverse mode
// if (outputsInfo == null) outputsInfo = this.outputsInfo(rootInfo, res);
//
// // process children if needed
// if (processChildren) {
// IResourceDelta[] children = delta.getAffectedChildren();
// boolean oneChildOnClasspath = false;
// int length = children.length;
// IResourceDelta[] orphanChildren = null;
// Openable parent = null;
// boolean isValidParent = true;
// for (int i = 0; i < length; i++) {
// IResourceDelta child = children[i];
// IResource childRes = child.getResource();
//
// // check source attachment change
// this.checkSourceAttachmentChange(child, childRes);
//
// // find out whether the child is a package fragment root of the current
// project
// IPath childPath = childRes.getFullPath();
// int childKind = child.getKind();
// RootInfo childRootInfo = this.rootInfo(childPath, childKind);
// if (childRootInfo != null && !childRootInfo.isRootOfProject(childPath)) {
// // package fragment root of another project (dealt with later)
// childRootInfo = null;
// }
//
// // compute child type
// int childType =
// this.elementType(
// childRes,
// childKind,
// elementType,
// rootInfo == null ? childRootInfo : rootInfo
// );
//
// // is childRes in the output folder and is it filtered out ?
// boolean isResFilteredFromOutput =
// this.isResFilteredFromOutput(outputsInfo, childRes, childType);
//
// boolean isNestedRoot = rootInfo != null && childRootInfo != null;
// if (!isResFilteredFromOutput
// && !isNestedRoot) { // do not treat as non-java rsc if nested root
//
// this.traverseDelta(child, childType, rootInfo == null ? childRootInfo :
// rootInfo, outputsInfo); // traverse delta for child in the same project
//
// if (childType == NON_JAVA_RESOURCE) {
// if (rootInfo != null) { // if inside a package fragment root
// if (!isValidParent) continue;
// if (parent == null) {
// // find the parent of the non-java resource to attach to
// if (this.currentElement == null
// || !rootInfo.project.equals(this.currentElement.getJavaProject())) { //
// note if currentElement is the IJavaModel, getJavaProject() is null
// // force the currentProject to be used
// this.currentElement = rootInfo.project;
// }
// if (elementType == IJavaElement.JAVA_PROJECT
// || (elementType == IJavaElement.PACKAGE_FRAGMENT_ROOT
// && res instanceof IProject)) {
// // NB: attach non-java resource to project (not to its package fragment
// root)
// parent = rootInfo.project;
// } else {
// parent = this.createElement(res, elementType, rootInfo);
// }
// if (parent == null) {
// isValidParent = false;
// continue;
// }
// }
// // add child as non java resource
// try {
// nonJavaResourcesChanged(parent, child);
// } catch (JavaModelException e) {
// // ignore
// }
// } else {
// // the non-java resource (or its parent folder) will be attached to the
// java project
// if (orphanChildren == null) orphanChildren = new IResourceDelta[length];
// orphanChildren[i] = child;
// }
// } else {
// oneChildOnClasspath = true;
// }
// } else {
// oneChildOnClasspath = true; // to avoid reporting child delta as non-java
// resource delta
// }
//
// // if child is a nested root
// // or if it is not a package fragment root of the current project
// // but it is a package fragment root of another project, traverse delta
// too
// if (isNestedRoot
// || (childRootInfo == null && (childRootInfo = this.rootInfo(childPath,
// childKind)) != null)) {
// this.traverseDelta(child, IJavaElement.PACKAGE_FRAGMENT_ROOT,
// childRootInfo, null); // binary output of childRootInfo.project cannot be
// this root
// }
//
// // if the child is a package fragment root of one or several other
// projects
// ArrayList rootList;
// if ((rootList = this.otherRootsInfo(childPath, childKind)) != null) {
// Iterator iterator = rootList.iterator();
// while (iterator.hasNext()) {
// childRootInfo = (RootInfo) iterator.next();
// this.traverseDelta(child, IJavaElement.PACKAGE_FRAGMENT_ROOT,
// childRootInfo, null); // binary output of childRootInfo.project cannot be
// this root
// }
// }
// }
// if (orphanChildren != null
// && (oneChildOnClasspath // orphan children are siblings of a package
// fragment root
// || res instanceof IProject)) { // non-java resource directly under a
// project
//
// // attach orphan children
// IProject rscProject = res.getProject();
// JavaProject adoptiveProject = (JavaProject)JavaCore.create(rscProject);
// if (adoptiveProject != null
// && JavaProject.hasJavaNature(rscProject)) { // delta iff Java project
// (18698)
// for (int i = 0; i < length; i++) {
// if (orphanChildren[i] != null) {
// try {
// nonJavaResourcesChanged(adoptiveProject, orphanChildren[i]);
// } catch (JavaModelException e) {
// // ignore
// }
// }
// }
// }
// } // else resource delta will be added by parent
// } // else resource delta will be added by parent
// }
private void notifyListeners(IJavaElementDelta deltaToNotify,
int eventType, IElementChangedListener[] listeners,
int[] listenerMask, int listenerCount) {
final ElementChangedEvent extraEvent = new ElementChangedEvent(
deltaToNotify, eventType);
for (int i = 0; i < listenerCount; i++) {
if ((listenerMask[i] & eventType) != 0) {
final IElementChangedListener listener = listeners[i];
long start = -1;
if (VERBOSE) {
System.out
.print("Listener #" + (i + 1) + "=" + listener.toString());//$NON-NLS-1$//$NON-NLS-2$
start = System.currentTimeMillis();
}
// wrap callbacks with Safe runnable for subsequent listeners to
// be called when some are causing grief
SafeRunner.run(new ISafeRunnable() {
public void handleException(Throwable exception) {
Util
.log(exception,
"Exception occurred in listener of Java element change notification"); //$NON-NLS-1$
}
public void run() throws Exception {
listener.elementChanged(extraEvent);
}
});
if (VERBOSE) {
System.out
.println(" -> " + (System.currentTimeMillis() - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
}
}
}
}
// private void notifyTypeHierarchies(IElementChangedListener[] listeners,
// int listenerCount) {
// for (int i= 0; i < listenerCount; i++) {
// final IElementChangedListener listener = listeners[i];
// if (!(listener instanceof TypeHierarchy)) continue;
//
// // wrap callbacks with Safe runnable for subsequent listeners to be
// called when some are causing grief
// Platform.run(new ISafeRunnable() {
// public void handleException(Throwable exception) {
// ProjectPrefUtil.log(exception, "Exception occurred in listener of Java
// element change notification"); //$NON-NLS-1$
// }
// public void run() throws Exception {
// TypeHierarchy typeHierarchy = (TypeHierarchy)listener;
// if (typeHierarchy.hasFineGrainChanges()) {
// // case of changes in primary working copies
// typeHierarchy.needsRefresh = true;
// typeHierarchy.fireChange();
// }
// }
// });
// }
// }
/*
* Generic processing for elements with changed contents: - The
* element is closed such that any subsequent accesses will re-open the
* element reflecting its new structure.
- An entry is made in the delta
* reporting a content change (K_CHANGE with F_CONTENT flag set).
*/
private void nonJavaResourcesChanged(Openable element, IResourceDelta delta)
throws JavaModelException {
// reset non-java resources if element was open
if (element.isOpen()) {
JavaElementInfo info = (JavaElementInfo) element.getElementInfo();
switch (element.getElementType()) {
case IJavaElement.JAVA_MODEL:
((JavaModelInfo) info).nonJavaResources = null;
currentDelta().addResourceDelta(delta);
return;
case IJavaElement.JAVA_PROJECT:
((JavaProjectElementInfo) info).setNonJavaResources(null);
// if a package fragment root is the project, clear it too
JavaProject project = (JavaProject) element;
PackageFragmentRoot projectRoot = (PackageFragmentRoot) project
.getPackageFragmentRoot(project.getProject());
if (projectRoot.isOpen()) {
((PackageFragmentRootInfo) projectRoot.getElementInfo())
.setNonJavaResources(null);
}
break;
case IJavaElement.PACKAGE_FRAGMENT:
((PackageFragmentInfo) info).setNonJavaResources(null);
break;
case IJavaElement.PACKAGE_FRAGMENT_ROOT:
((PackageFragmentRootInfo) info).setNonJavaResources(null);
}
}
JavaElementDelta current = currentDelta();
JavaElementDelta elementDelta = current.find(element);
if (elementDelta == null) {
// don't use find after creating the delta as it can be null (see
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=63434)
elementDelta = current
.changed(element, IJavaElementDelta.F_CONTENT);
}
elementDelta.addResourceDelta(delta);
}
/*
* Flushes all deltas without firing them.
*/
public void flush() {
this.javaModelDeltas = new ArrayList();
}
/*
* Finds the root info this path is included in. Returns null if not found.
*/
// RootInfo enclosingRootInfo(IPath path, int kind) {
// while (path != null && path.segmentCount() > 0) {
// RootInfo rootInfo = this.rootInfo(path, kind);
// if (rootInfo != null)
// return rootInfo;
// path = path.removeLastSegments(1);
// }
// return null;
// }
/*
* Fire Java Model delta, flushing them after the fact after post_change
* notification. If the firing mode has been turned off, this has no effect.
*/
public void fire(IJavaElementDelta customDelta, int eventType) {
if (!this.isFiring)
return;
if (DEBUG) {
System.out
.println("-----------------------------------------------------------------------------------------------------------------------");//$NON-NLS-1$
}
IJavaElementDelta deltaToNotify;
if (customDelta == null) {
deltaToNotify = this.mergeDeltas(this.javaModelDeltas);
} else {
deltaToNotify = customDelta;
}
// Refresh internal scopes
// if (deltaToNotify != null) {
// Iterator scopes = this.manager.searchScopes.keySet().iterator();
// while (scopes.hasNext()) {
// AbstractSearchScope scope = (AbstractSearchScope)scopes.next();
// scope.processDelta(deltaToNotify);
// }
// }
// Notification
// Important: if any listener reacts to notification by updating the
// listeners list or mask, these lists will
// be duplicated, so it is necessary to remember original lists in a
// variable (since field values may change under us)
IElementChangedListener[] listeners = this.state.elementChangedListeners;
int[] listenerMask = this.state.elementChangedListenerMasks;
int listenerCount = this.state.elementChangedListenerCount;
switch (eventType) {
case DEFAULT_CHANGE_EVENT:
firePostChangeDelta(deltaToNotify, listeners, listenerMask,
listenerCount);
fireReconcileDelta(listeners, listenerMask, listenerCount);
break;
case ElementChangedEvent.POST_CHANGE:
firePostChangeDelta(deltaToNotify, listeners, listenerMask,
listenerCount);
fireReconcileDelta(listeners, listenerMask, listenerCount);
break;
}
}
private void firePostChangeDelta(IJavaElementDelta deltaToNotify,
IElementChangedListener[] listeners, int[] listenerMask,
int listenerCount) {
// post change deltas
if (DEBUG) {
System.out
.println("FIRING POST_CHANGE Delta [" + Thread.currentThread() + "]:"); //$NON-NLS-1$//$NON-NLS-2$
System.out
.println(deltaToNotify == null ? "" : deltaToNotify.toString()); //$NON-NLS-1$
}
if (deltaToNotify != null) {
// flush now so as to keep listener reactions to post their own
// deltas for subsequent iteration
this.flush();
notifyListeners(deltaToNotify, ElementChangedEvent.POST_CHANGE,
listeners, listenerMask, listenerCount);
}
}
private void fireReconcileDelta(IElementChangedListener[] listeners,
int[] listenerMask, int listenerCount) {
IJavaElementDelta deltaToNotify = mergeDeltas(this.reconcileDeltas
.values());
if (DEBUG) {
System.out
.println("FIRING POST_RECONCILE Delta [" + Thread.currentThread() + "]:"); //$NON-NLS-1$//$NON-NLS-2$
System.out
.println(deltaToNotify == null ? "" : deltaToNotify.toString()); //$NON-NLS-1$
}
if (deltaToNotify != null) {
// flush now so as to keep listener reactions to post their own
// deltas for subsequent iteration
this.reconcileDeltas = new HashMap();
notifyListeners(deltaToNotify, ElementChangedEvent.POST_RECONCILE,
listeners, listenerMask, listenerCount);
}
}
/*
* Returns the root info for the given path. Look in the old roots table if
* kind is REMOVED.
*/
// RootInfo rootInfo(IPath path, int kind) {
// if (kind == IResourceDelta.REMOVED) {
// return (RootInfo) this.oldRoots.get(path);
// } else {
// return (RootInfo) this.roots.get(path);
// }
// }
/*
* Returns the other root infos for the given path. Look in the old other
* roots table if kind is REMOVED.
*/
// ArrayList otherRootsInfo(IPath path, int kind) {
// if (kind == IResourceDelta.REMOVED) {
// return (ArrayList) this.oldOtherRoots.get(path);
// } else {
// return (ArrayList) this.otherRoots.get(path);
// }
// }
/**
* Converts an IResourceDelta
and its children into the
* corresponding IJavaElementDelta
s. Return whether the
* delta corresponds to a java element. If it is not a java element, it will
* be added as a non-java resource by the sender of this method.
*/
// protected boolean traverseDelta(
// IResourceDelta delta,
// int elementType,
// RootInfo rootInfo,
// OutputsInfo outputsInfo) {
//
// IResource res = delta.getResource();
//
// // set stack of elements
// if (this.currentElement == null && rootInfo != null) {
// this.currentElement = (Openable)rootInfo.project;
// }
//
// // process current delta
// boolean processChildren = true;
// if (res instanceof IProject) {
// processChildren =
// this.updateCurrentDeltaAndIndex(
// delta,
// elementType == IJavaElement.PACKAGE_FRAGMENT_ROOT ?
// IJavaElement.JAVA_PROJECT : // case of prj=src
// elementType,
// rootInfo);
// } else if (rootInfo != null) {
// processChildren = this.updateCurrentDeltaAndIndex(delta, elementType,
// rootInfo);
// } else {
// // not yet inside a package fragment root
// processChildren = true;
// }
//
// // get the project's output locations and traverse mode
// if (outputsInfo == null) outputsInfo = this.outputsInfo(rootInfo, res);
//
// // process children if needed
// if (processChildren) {
// IResourceDelta[] children = delta.getAffectedChildren();
// boolean oneChildOnClasspath = false;
// int length = children.length;
// IResourceDelta[] orphanChildren = null;
// Openable parent = null;
// boolean isValidParent = true;
// for (int i = 0; i < length; i++) {
// IResourceDelta child = children[i];
// IResource childRes = child.getResource();
//
// // check source attachment change
// this.checkSourceAttachmentChange(child, childRes);
//
// // find out whether the child is a package fragment root of the current
// project
// IPath childPath = childRes.getFullPath();
// int childKind = child.getKind();
// RootInfo childRootInfo = this.rootInfo(childPath, childKind);
// if (childRootInfo != null && !childRootInfo.isRootOfProject(childPath)) {
// // package fragment root of another project (dealt with later)
// childRootInfo = null;
// }
//
// // compute child type
// int childType =
// this.elementType(
// childRes,
// childKind,
// elementType,
// rootInfo == null ? childRootInfo : rootInfo
// );
//
// // is childRes in the output folder and is it filtered out ?
// boolean isResFilteredFromOutput =
// this.isResFilteredFromOutput(outputsInfo, childRes, childType);
//
// boolean isNestedRoot = rootInfo != null && childRootInfo != null;
// if (!isResFilteredFromOutput
// && !isNestedRoot) { // do not treat as non-java rsc if nested root
// if (!this.traverseDelta(child, childType, rootInfo == null ?
// childRootInfo : rootInfo, outputsInfo)) { // traverse delta for child in
// the same project
// // it is a non-java resource
// try {
// if (rootInfo != null) { // if inside a package fragment root
// if (!isValidParent) continue;
// if (parent == null) {
// // find the parent of the non-java resource to attach to
// if (this.currentElement == null
// || !this.currentElement.getJavaProject().equals(rootInfo.project)) {
// // force the currentProject to be used
// this.currentElement = (Openable)rootInfo.project;
// }
// if (elementType == IJavaElement.JAVA_PROJECT
// || (elementType == IJavaElement.PACKAGE_FRAGMENT_ROOT
// && res instanceof IProject)) {
// // NB: attach non-java resource to project (not to its package fragment
// root)
// parent = (Openable)rootInfo.project;
// } else {
// parent = this.createElement(res, elementType, rootInfo);
// }
// if (parent == null) {
// isValidParent = false;
// continue;
// }
// }
// // add child as non java resource
// nonJavaResourcesChanged(parent, child);
// } else {
// // the non-java resource (or its parent folder) will be attached to the
// java project
// if (orphanChildren == null) orphanChildren = new IResourceDelta[length];
// orphanChildren[i] = child;
// }
// } catch (JavaModelException e) {
// }
// } else {
// oneChildOnClasspath = true;
// }
// } else {
// oneChildOnClasspath = true; // to avoid reporting child delta as non-java
// resource delta
// }
//
// // if child is a nested root
// // or if it is not a package fragment root of the current project
// // but it is a package fragment root of another project, traverse delta
// too
// if (isNestedRoot
// || (childRootInfo == null && (childRootInfo = this.rootInfo(childPath,
// childKind)) != null)) {
// this.traverseDelta(child, IJavaElement.PACKAGE_FRAGMENT_ROOT,
// childRootInfo, null); // binary output of childRootInfo.project cannot be
// this root
// // NB: No need to check the return value as the child can only be on the
// classpath
// }
//
// // if the child is a package fragment root of one or several other
// projects
// ArrayList rootList;
// if ((rootList = this.otherRootsInfo(childPath, childKind)) != null) {
// Iterator iterator = rootList.iterator();
// while (iterator.hasNext()) {
// childRootInfo = (RootInfo) iterator.next();
// this.traverseDelta(child, IJavaElement.PACKAGE_FRAGMENT_ROOT,
// childRootInfo, null); // binary output of childRootInfo.project cannot be
// this root
// }
// }
// }
// if (orphanChildren != null
// && (oneChildOnClasspath // orphan children are siblings of a package
// fragment root
// || res instanceof IProject)) { // non-java resource directly under a
// project
//
// // attach orphan children
// IProject rscProject = res.getProject();
// JavaProject adoptiveProject = (JavaProject)JavaCore.create(rscProject);
// if (adoptiveProject != null
// && JavaProject.hasJavaNature(rscProject)) { // delta iff Java project
// (18698)
// for (int i = 0; i < length; i++) {
// if (orphanChildren[i] != null) {
// try {
// nonJavaResourcesChanged(adoptiveProject, orphanChildren[i]);
// } catch (JavaModelException e) {
// }
// }
// }
// }
// } // else resource delta will be added by parent
// return elementType != NON_JAVA_RESOURCE; // TODO: (jerome) do we still
// need to return? (check could be done by caller)
// } else {
// return elementType != NON_JAVA_RESOURCE;
// }
// }
/**
* Update the classpath markers and cycle markers for the projects to
* update.
*/
// void updateClasspathMarkers() {
// try {
// if (!ResourcesPlugin.getWorkspace().isAutoBuilding()) {
// Iterator iterator = this.projectsToUpdate.iterator();
// while (iterator.hasNext()) {
// try {
// JavaProject project = (JavaProject)iterator.next();
//
// // force classpath marker refresh
// project.getResolvedClasspath(
// true, // ignoreUnresolvedEntry
// true); // generateMarkerOnError
//
// } catch (JavaModelException e) {
// }
// }
// }
// if (!this.projectsToUpdate.isEmpty()){
// try {
// // update all cycle markers
// JavaProject.updateAllCycleMarkers();
// } catch (JavaModelException e) {
// }
// }
// } finally {
// this.projectsToUpdate = new HashSet();
// }
// }
/*
* Update the current delta (ie. add/remove/change the given element) and
* update the correponding index. Returns whether the children of the given
* delta must be processed. @throws a JavaModelException if the delta
* doesn't correspond to a java element of the given type.
*/
// private boolean updateCurrentDeltaAndIndex(IResourceDelta delta, int
// elementType, RootInfo rootInfo) {
// Openable element;
// switch (delta.getKind()) {
// case IResourceDelta.ADDED :
// IResource deltaRes = delta.getResource();
// element = this.createElement(deltaRes, elementType, rootInfo);
// if (element == null) {
// // resource might be containing shared roots (see bug 19058)
// this.updateRoots(deltaRes.getFullPath(), delta);
// return false;
// }
// this.updateIndex(element, delta);
// this.elementAdded(element, delta, rootInfo);
// return false;
// case IResourceDelta.REMOVED :
// deltaRes = delta.getResource();
// element = this.createElement(deltaRes, elementType, rootInfo);
// if (element == null) {
// // resource might be containing shared roots (see bug 19058)
// this.updateRoots(deltaRes.getFullPath(), delta);
// return false;
// }
// this.updateIndex(element, delta);
// this.elementRemoved(element, delta, rootInfo);
//
// if (deltaRes.getType() == IResource.PROJECT){
// // reset the corresponding project built state, since cannot reuse if
// added back
// this.manager.setLastBuiltState((IProject)deltaRes, null /*no state*/);
// }
// return false;
// case IResourceDelta.CHANGED :
// int flags = delta.getFlags();
// if ((flags & IResourceDelta.CONTENT) != 0) {
// // content has changed
// element = this.createElement(delta.getResource(), elementType, rootInfo);
// if (element == null) return false;
// this.updateIndex(element, delta);
// this.contentChanged(element, delta);
// } else if (elementType == IJavaElement.JAVA_PROJECT) {
// if ((flags & IResourceDelta.OPEN) != 0) {
// // project has been opened or closed
// IProject res = (IProject)delta.getResource();
// element = this.createElement(res, elementType, rootInfo);
// if (element == null) {
// // resource might be containing shared roots (see bug 19058)
// this.updateRoots(res.getFullPath(), delta);
// return false;
// }
// if (res.isOpen()) {
// if (JavaProject.hasJavaNature(res)) {
// this.elementAdded(element, delta, rootInfo);
// this.indexManager.indexAll(res);
// }
// } else {
// JavaModel javaModel = this.manager.getJavaModel();
// boolean wasJavaProject = javaModel.findJavaProject(res) != null;
// if (wasJavaProject) {
// this.elementRemoved(element, delta, rootInfo);
// this.indexManager.discardJobs(element.getElementName());
// this.indexManager.removeIndexFamily(res.getFullPath());
//
// }
// }
// return false; // when a project is open/closed don't process children
// }
// if ((flags & IResourceDelta.DESCRIPTION) != 0) {
// IProject res = (IProject)delta.getResource();
// JavaModel javaModel = this.manager.getJavaModel();
// boolean wasJavaProject = javaModel.findJavaProject(res) != null;
// boolean isJavaProject = JavaProject.hasJavaNature(res);
// if (wasJavaProject != isJavaProject) {
// // project's nature has been added or removed
// element = this.createElement(res, elementType, rootInfo);
// if (element == null) return false; // note its resources are still
// visible as roots to other projects
// if (isJavaProject) {
// this.elementAdded(element, delta, rootInfo);
// this.indexManager.indexAll(res);
// } else {
// this.elementRemoved(element, delta, rootInfo);
// this.indexManager.discardJobs(element.getElementName());
// this.indexManager.removeIndexFamily(res.getFullPath());
// // reset the corresponding project built state, since cannot reuse if
// added back
// this.manager.setLastBuiltState(res, null /*no state*/);
// }
// return false; // when a project's nature is added/removed don't process
// children
// }
// }
// }
// return true;
// }
// return true;
// }
/**
* Traverse the set of projects which have changed namespace, and refresh
* their dependents
*/
// public void updateDependentNamelookups() {
// Iterator iterator;
// // update namelookup of dependent projects
// iterator = this.projectsForDependentNamelookupRefresh.iterator();
// HashSet affectedDependents = new HashSet();
// while (iterator.hasNext()) {
// JavaProject project = (JavaProject)iterator.next();
// addDependentProjects(project.getPath(), affectedDependents);
// }
// iterator = affectedDependents.iterator();
// while (iterator.hasNext()) {
// JavaProject project = (JavaProject) iterator.next();
// if (project.isOpen()){
// try {
// ((JavaProjectElementInfo)project.getElementInfo()).setNameLookup(null);
// } catch (JavaModelException e) {
// }
// }
// }
// }
// protected void updateIndex(Openable element, IResourceDelta delta) {
//
// if (indexManager == null)
// return;
//
// switch (element.getElementType()) {
// case IJavaElement.JAVA_PROJECT :
// switch (delta.getKind()) {
// case IResourceDelta.ADDED :
// this.indexManager.indexAll(element.getJavaProject().getProject());
// break;
// case IResourceDelta.REMOVED :
// this.indexManager.removeIndexFamily(element.getJavaProject().getProject().getFullPath());
// // NB: Discarding index jobs belonging to this project was done during
// PRE_DELETE
// break;
// // NB: Update of index if project is opened, closed, or its java nature
// is added or removed
// // is done in updateCurrentDeltaAndIndex
// }
// break;
// case IJavaElement.PACKAGE_FRAGMENT_ROOT :
// if (element instanceof JarPackageFragmentRoot) {
// JarPackageFragmentRoot root = (JarPackageFragmentRoot)element;
// // index jar file only once (if the root is in its declaring project)
// IPath jarPath = root.getPath();
// switch (delta.getKind()) {
// case IResourceDelta.ADDED:
// // index the new jar
// indexManager.indexLibrary(jarPath, root.getJavaProject().getProject());
// break;
// case IResourceDelta.CHANGED:
// // first remove the index so that it is forced to be re-indexed
// indexManager.removeIndex(jarPath);
// // then index the jar
// indexManager.indexLibrary(jarPath, root.getJavaProject().getProject());
// break;
// case IResourceDelta.REMOVED:
// // the jar was physically removed: remove the index
// this.indexManager.discardJobs(jarPath.toString());
// this.indexManager.removeIndex(jarPath);
// break;
// }
// break;
// } else {
// int kind = delta.getKind();
// if (kind == IResourceDelta.ADDED || kind == IResourceDelta.REMOVED) {
// IPackageFragmentRoot root = (IPackageFragmentRoot)element;
// this.updateRootIndex(root, root.getPackageFragment(""), delta);
// //$NON-NLS-1$
// break;
// }
// }
// // don't break as packages of the package fragment root can be indexed
// below
// case IJavaElement.PACKAGE_FRAGMENT :
// switch (delta.getKind()) {
// case IResourceDelta.ADDED:
// case IResourceDelta.REMOVED:
// IPackageFragment pkg = null;
// if (element instanceof IPackageFragmentRoot) {
// IPackageFragmentRoot root = (IPackageFragmentRoot)element;
// pkg = root.getPackageFragment(""); //$NON-NLS-1$
// } else {
// pkg = (IPackageFragment)element;
// }
// IResourceDelta[] children = delta.getAffectedChildren();
// for (int i = 0, length = children.length; i < length; i++) {
// IResourceDelta child = children[i];
// IResource resource = child.getResource();
// if (resource instanceof IFile) {
// String name = resource.getName();
// if (ProjectPrefUtil.isJavaFileName(name)) {
// Openable cu = (Openable)pkg.getCompilationUnit(name);
// this.updateIndex(cu, child);
// } else if (ProjectPrefUtil.isClassFileName(name)) {
// Openable classFile = (Openable)pkg.getClassFile(name);
// this.updateIndex(classFile, child);
// }
// }
// }
// break;
// }
// break;
// case IJavaElement.CLASS_FILE :
// IFile file = (IFile) delta.getResource();
// IJavaProject project = element.getJavaProject();
// IPath binaryFolderPath = element.getPackageFragmentRoot().getPath();
// // if the class file is part of the binary output, it has been created by
// // the java builder -> ignore
// try {
// if (binaryFolderPath.equals(project.getOutputLocation())) {
// break;
// }
// } catch (JavaModelException e) {
// }
// switch (delta.getKind()) {
// case IResourceDelta.CHANGED :
// // no need to index if the content has not changed
// if ((delta.getFlags() & IResourceDelta.CONTENT) == 0)
// break;
// case IResourceDelta.ADDED :
// indexManager.addBinary(file, binaryFolderPath);
// break;
// case IResourceDelta.REMOVED :
// indexManager.remove(file.getFullPath().toString(), binaryFolderPath);
// break;
// }
// break;
// case IJavaElement.COMPILATION_UNIT :
// file = (IFile) delta.getResource();
// switch (delta.getKind()) {
// case IResourceDelta.CHANGED :
// // no need to index if the content has not changed
// if ((delta.getFlags() & IResourceDelta.CONTENT) == 0)
// break;
// case IResourceDelta.ADDED :
// indexManager.addSource(file,
// file.getProject().getProject().getFullPath());
// break;
// case IResourceDelta.REMOVED :
// indexManager.remove(file.getFullPath().toString(),
// file.getProject().getProject().getFullPath());
// break;
// }
// }
// }
/**
* Upadtes the index of the given root (assuming it's an addition or a
* removal). This is done recusively, pkg being the current package.
*/
// private void updateRootIndex(IPackageFragmentRoot root, IPackageFragment
// pkg, IResourceDelta delta) {
// this.updateIndex((Openable)pkg, delta);
// IResourceDelta[] children = delta.getAffectedChildren();
// String name = pkg.getElementName();
// for (int i = 0, length = children.length; i < length; i++) {
// IResourceDelta child = children[i];
// IResource resource = child.getResource();
// if (resource instanceof IFolder) {
// String subpkgName =
// name.length() == 0 ?
// resource.getName() :
// name + "." + resource.getName(); //$NON-NLS-1$
// IPackageFragment subpkg = root.getPackageFragment(subpkgName);
// this.updateRootIndex(root, subpkg, child);
// }
// }
// }
/*
* Update the roots that are affected by the addition or the removal of the
* given container resource.
*/
// private void updateRoots(IPath containerPath, IResourceDelta
// containerDelta) {
// Map roots;
// Map otherRoots;
// if (containerDelta.getKind() == IResourceDelta.REMOVED) {
// roots = this.oldRoots;
// otherRoots = this.oldOtherRoots;
// } else {
// roots = this.roots;
// otherRoots = this.otherRoots;
// }
// Iterator iterator = roots.keySet().iterator();
// while (iterator.hasNext()) {
// IPath path = (IPath)iterator.next();
// if (containerPath.isPrefixOf(path) && !containerPath.equals(path)) {
// IResourceDelta rootDelta =
// containerDelta.findMember(path.removeFirstSegments(1));
// if (rootDelta == null) continue;
// RootInfo rootInfo = (RootInfo)roots.get(path);
//
// if (!rootInfo.project.getPath().isPrefixOf(path)) { // only consider
// roots that are not included in the container
// this.updateCurrentDeltaAndIndex(rootDelta,
// IJavaElement.PACKAGE_FRAGMENT_ROOT, rootInfo);
// }
//
// ArrayList rootList = (ArrayList)otherRoots.get(path);
// if (rootList != null) {
// Iterator otherProjects = rootList.iterator();
// while (otherProjects.hasNext()) {
// rootInfo = (RootInfo)otherProjects.next();
// if (!rootInfo.project.getPath().isPrefixOf(path)) { // only consider
// roots that are not included in the container
// this.updateCurrentDeltaAndIndex(rootDelta,
// IJavaElement.PACKAGE_FRAGMENT_ROOT, rootInfo);
// }
// }
// }
// }
// }
// }
}