JavaModelManager
manages instances of IJavaModel
.
@@ -76,13 +82,12 @@ import org.eclipse.core.runtime.Status;
* The single instance of JavaModelManager
is available from
* the static method JavaModelManager.getJavaModelManager()
.
*/
-public class JavaModelManager implements ISaveParticipant {
-
- /**
+public class JavaModelManager implements ISaveParticipant {
+ /**
* Unique handle onto the JavaModel
*/
final JavaModel javaModel = new JavaModel();
-
+// public IndexManager indexManager = new IndexManager();
/**
* Classpath variables pool
*/
@@ -90,13 +95,13 @@ public class JavaModelManager implements ISaveParticipant {
public static HashMap PreviousSessionVariables = new HashMap(5);
public static HashSet OptionNames = new HashSet(20);
public final static String CP_VARIABLE_PREFERENCES_PREFIX = PHPeclipsePlugin.PLUGIN_ID+".classpathVariable."; //$NON-NLS-1$
-// public final static String CP_CONTAINER_PREFERENCES_PREFIX = PHPCore.PLUGIN_ID+".classpathContainer."; //$NON-NLS-1$
+ public final static String CP_CONTAINER_PREFERENCES_PREFIX = PHPeclipsePlugin.PLUGIN_ID+".classpathContainer."; //$NON-NLS-1$
public final static String CP_ENTRY_IGNORE = "##null
if unable to associate the given folder with a Java element.
*
* Note that a package fragment root is returned rather than a default package.
@@ -311,11 +326,11 @@ public class JavaModelManager implements ISaveParticipant {
return null;
}
if (project == null) {
- project = PHPCore.create(folder.getProject());
+ project = JavaCore.create(folder.getProject());
}
IJavaElement element = determineIfOnClasspath(folder, project);
if (conflictsWithOutputLocation(folder.getFullPath(), (JavaProject)project)
- || (folder.getName().indexOf('.') >= 0
+ || (folder.getName().indexOf('.') >= 0
&& !(element instanceof IPackageFragmentRoot))) {
return null; // only package fragment roots are allowed with dot names
} else {
@@ -344,9 +359,9 @@ public class JavaModelManager implements ISaveParticipant {
// }
// return pkg.getClassFile(file.getName());
// }
-
+
/**
- * Creates and returns a compilation unit element for the given .java
+ * Creates and returns a compilation unit element for the given .java
* file, its project being the given project. Returns null
if unable
* to recognize the compilation unit.
*/
@@ -355,14 +370,14 @@ public class JavaModelManager implements ISaveParticipant {
if (file == null) return null;
if (project == null) {
- project = PHPCore.create(file.getProject());
+ project = JavaCore.create(file.getProject());
}
IPackageFragment pkg = (IPackageFragment) determineIfOnClasspath(file, project);
if (pkg == null) {
// not on classpath - make the root its folder, and a default package
IPackageFragmentRoot root = project.getPackageFragmentRoot(file.getParent());
pkg = root.getPackageFragment(IPackageFragment.DEFAULT_PACKAGE_NAME);
-
+
if (VERBOSE){
System.out.println("WARNING : creating unit element outside classpath ("+ Thread.currentThread()+"): " + file.getFullPath()); //$NON-NLS-1$//$NON-NLS-2$
}
@@ -372,7 +387,7 @@ public class JavaModelManager implements ISaveParticipant {
/**
* Creates and returns a handle for the given JAR file, its project being the given project.
* The Java model associated with the JAR's project may be
- * created as a side effect.
+ * created as a side effect.
* Returns null
if unable to create a JAR package fragment root.
* (for example, if the JAR file represents a non-Java resource)
*/
@@ -383,7 +398,7 @@ public class JavaModelManager implements ISaveParticipant {
// if (project == null) {
// project = PHPCore.create(file.getProject());
// }
-//
+//
// // Create a jar package fragment root only if on the classpath
// IPath resourcePath = file.getFullPath();
// try {
@@ -399,7 +414,7 @@ public class JavaModelManager implements ISaveParticipant {
// }
// return null;
// }
-
+
/**
* Returns the package fragment root represented by the resource, or
* the package fragment the given resource is located in, or null
@@ -408,21 +423,21 @@ public class JavaModelManager implements ISaveParticipant {
public static IJavaElement determineIfOnClasspath(
IResource resource,
IJavaProject project) {
-
+
IPath resourcePath = resource.getFullPath();
try {
- IClasspathEntry[] entries =
- Util.isJavaFileName(resourcePath.lastSegment())
+ IClasspathEntry[] entries =
+ net.sourceforge.phpdt.internal.compiler.util.Util.isJavaFileName(resourcePath.lastSegment())
? project.getRawClasspath() // JAVA file can only live inside SRC folder (on the raw path)
: ((JavaProject)project).getResolvedClasspath(true);
-
+
for (int i = 0; i < entries.length; i++) {
IClasspathEntry entry = entries[i];
if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) continue;
IPath rootPath = entry.getPath();
if (rootPath.equals(resourcePath)) {
return project.getPackageFragmentRoot(resource);
- } else if (rootPath.isPrefixOf(resourcePath) && !Util.isExcluded(resource, ((ClasspathEntry)entry).fullExclusionPatternChars())) {
+ } else if (rootPath.isPrefixOf(resourcePath) && !Util.isExcluded(resource, null, ((ClasspathEntry)entry).fullExclusionPatternChars())) {
// given we have a resource child of the root, it cannot be a JAR pkg root
IPackageFragmentRoot root = ((JavaProject) project).getFolderPackageFragmentRoot(rootPath);
if (root == null) return null;
@@ -431,9 +446,10 @@ public class JavaModelManager implements ISaveParticipant {
// if the resource is a file, then remove the last segment which
// is the file name in the package
pkgPath = pkgPath.removeLastSegments(1);
-
+
// don't check validity of package name (see http://bugs.eclipse.org/bugs/show_bug.cgi?id=26706)
- String pkgName = pkgPath.toString().replace('/', '.');
+// String pkgName = pkgPath.toString().replace('/', '.');
+ String pkgName = pkgPath.toString();
return root.getPackageFragment(pkgName);
} else {
String pkgName = Util.packageName(pkgPath);
@@ -449,7 +465,7 @@ public class JavaModelManager implements ISaveParticipant {
}
return null;
}
-
+
/**
* The singleton manager
*/
@@ -460,11 +476,18 @@ public class JavaModelManager implements ISaveParticipant {
*/
protected JavaModelCache cache = new JavaModelCache();
+ /*
+ * Temporary cache of newly opened elements
+ */
+ private ThreadLocal temporaryCache = new ThreadLocal();
/**
* Set of elements which are out of sync with their buffers.
*/
protected Map elementsOutOfSynchWithBuffers = new HashMap(11);
-
+ /**
+ * Holds the state used for delta processing.
+ */
+ public DeltaProcessingState deltaState = new DeltaProcessingState();
/**
* Turns delta firing on/off. By default it is on.
*/
@@ -496,13 +519,13 @@ public class JavaModelManager implements ISaveParticipant {
/**
* Used to convert IResourceDelta
s into IJavaElementDelta
s.
*/
- public final DeltaProcessor deltaProcessor = new DeltaProcessor(this);
+// public final DeltaProcessor deltaProcessor = new DeltaProcessor(this);
/**
* Used to update the JavaModel for IJavaElementDelta
s.
*/
-// private final ModelUpdater modelUpdater =new ModelUpdater();
+ private final ModelUpdater modelUpdater =new ModelUpdater();
/**
- * Workaround for bug 15168 circular errors not reported
+ * Workaround for bug 15168 circular errors not reported
* This is a cache of the projects before any project addition/deletion has started.
*/
public IJavaProject[] javaProjectsCache;
@@ -512,46 +535,144 @@ public class JavaModelManager implements ISaveParticipant {
* NOTE: this object itself is used as a lock to synchronize creation/removal of per project infos
*/
protected Map perProjectInfo = new HashMap(5);
-
+
/**
* A map from ICompilationUnit to IWorkingCopy
* of the shared working copies.
*/
public Map sharedWorkingCopies = new HashMap();
-
+
/**
* A weak set of the known scopes.
*/
- protected WeakHashMap scopes = new WeakHashMap();
+ protected WeakHashMap searchScopes = new WeakHashMap();
+
+// public static class PerProjectInfo {
+// public IProject project;
+// public Object savedState;
+// public boolean triedRead;
+// public IClasspathEntry[] classpath;
+// public IClasspathEntry[] lastResolvedClasspath;
+// public Map resolvedPathToRawEntries; // reverse map from resolved path to raw entries
+// public IPath outputLocation;
+// public Preferences preferences;
+// public PerProjectInfo(IProject project) {
+//
+// this.triedRead = false;
+// this.savedState = null;
+// this.project = project;
+// }
+// }
public static class PerProjectInfo {
+
public IProject project;
public Object savedState;
public boolean triedRead;
- public IClasspathEntry[] classpath;
- public IClasspathEntry[] lastResolvedClasspath;
+ public IClasspathEntry[] rawClasspath;
+ public IClasspathEntry[] resolvedClasspath;
public Map resolvedPathToRawEntries; // reverse map from resolved path to raw entries
public IPath outputLocation;
public Preferences preferences;
+
public PerProjectInfo(IProject project) {
this.triedRead = false;
this.savedState = null;
this.project = project;
}
+
+ // updating raw classpath need to flush obsoleted cached information about resolved entries
+ public synchronized void updateClasspathInformation(IClasspathEntry[] newRawClasspath) {
+
+ this.rawClasspath = newRawClasspath;
+ this.resolvedClasspath = null;
+ this.resolvedPathToRawEntries = null;
+ }
+ public String toString() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("Info for "); //$NON-NLS-1$
+ buffer.append(this.project.getFullPath());
+ buffer.append("\nRaw classpath:\n"); //$NON-NLS-1$
+ if (this.rawClasspath == null) {
+ buffer.append(" IJavaElement
represented by the
+ * Returns the IJavaElement
represented by the
* String
memento.
*/
public IJavaElement getHandleFromMemento(String memento) throws JavaModelException {
@@ -904,7 +1075,7 @@ public class JavaModelManager implements ISaveParticipant {
return proj;
}
int rootEnd= memento.indexOf(JavaElement.JEM_PACKAGEFRAGMENT, projectEnd + 1);
-// TODO khartlage temp-del
+// TODO temp-del
// if (rootEnd == -1) {
// return model.getHandleFromMementoForRoot(memento, proj, projectEnd, memento.length());
// }
@@ -989,8 +1160,8 @@ public class JavaModelManager implements ISaveParticipant {
}
return info;
}
- }
-
+ }
+
/*
* Returns the per-project info for the given project.
* If the info doesn't exist, check for the project existence and create the info.
@@ -1000,19 +1171,42 @@ public class JavaModelManager implements ISaveParticipant {
JavaModelManager.PerProjectInfo info = getPerProjectInfo(project, false /* don't create info */);
if (info == null) {
if (!JavaProject.hasJavaNature(project)) {
- throw ((JavaProject)PHPCore.create(project)).newNotPresentException();
+ throw ((JavaProject)JavaCore.create(project)).newNotPresentException();
}
info = getPerProjectInfo(project, true /* create info */);
}
return info;
}
+ /*
+ * Returns the per-working copy info for the given working copy at the given path.
+ * If it doesn't exist and if create, add a new per-working copy info with the given problem requestor.
+ * If recordUsage, increment the per-working copy info's use count.
+ * Returns null if it doesn't exist and not create.
+ */
+ public PerWorkingCopyInfo getPerWorkingCopyInfo(CompilationUnit workingCopy,boolean create, boolean recordUsage, IProblemRequestor problemRequestor) {
+ synchronized(perWorkingCopyInfos) { // use the perWorkingCopyInfo collection as its own lock
+ WorkingCopyOwner owner = workingCopy.owner;
+ Map workingCopyToInfos = (Map)this.perWorkingCopyInfos.get(owner);
+ if (workingCopyToInfos == null && create) {
+ workingCopyToInfos = new HashMap();
+ this.perWorkingCopyInfos.put(owner, workingCopyToInfos);
+ }
+ PerWorkingCopyInfo info = workingCopyToInfos == null ? null : (PerWorkingCopyInfo) workingCopyToInfos.get(workingCopy);
+ if (info == null && create) {
+ info= new PerWorkingCopyInfo(workingCopy, problemRequestor);
+ workingCopyToInfos.put(workingCopy, info);
+ }
+ if (info != null && recordUsage) info.useCount++;
+ return info;
+ }
+ }
/**
* Returns the name of the variables for which an CP variable initializer is registered through an extension point
*/
public static String[] getRegisteredVariableNames(){
-
- Plugin jdtCorePlugin = PHPCore.getPlugin();
+
+ Plugin jdtCorePlugin = JavaCore.getPlugin();
if (jdtCorePlugin == null) return null;
ArrayList variableList = new ArrayList(5);
@@ -1025,18 +1219,18 @@ public class JavaModelManager implements ISaveParticipant {
// String varAttribute = configElements[j].getAttribute("variable"); //$NON-NLS-1$
// if (varAttribute != null) variableList.add(varAttribute);
// }
-// }
+// }
// }
String[] variableNames = new String[variableList.size()];
variableList.toArray(variableNames);
return variableNames;
- }
+ }
/**
* Returns the name of the container IDs for which an CP container initializer is registered through an extension point
*/
// public static String[] getRegisteredContainerIDs(){
-//
+//
// Plugin jdtCorePlugin = PHPCore.getPlugin();
// if (jdtCorePlugin == null) return null;
//
@@ -1050,23 +1244,34 @@ public class JavaModelManager implements ISaveParticipant {
// String idAttribute = configElements[j].getAttribute("id"); //$NON-NLS-1$
// if (idAttribute != null) containerIDList.add(idAttribute);
// }
-// }
+// }
// }
// String[] containerIDs = new String[containerIDList.size()];
// containerIDList.toArray(containerIDs);
// return containerIDs;
-// }
+// }
/**
* Returns the File to use for saving and restoring the last built state for the given project.
*/
private File getSerializationFile(IProject project) {
if (!project.exists()) return null;
- IPluginDescriptor descr= PHPCore.getJavaCore().getDescriptor();
- IPath workingLocation= project.getPluginWorkingLocation(descr);
+ IPath workingLocation = project.getWorkingLocation(JavaCore.PLUGIN_ID);
return workingLocation.append("state.dat").toFile(); //$NON-NLS-1$
}
+ /*
+ * Returns the temporary cache for newly opened elements for the current thread.
+ * Creates it if not already created.
+ */
+ public HashMap getTemporaryCache() {
+ HashMap result = (HashMap)this.temporaryCache.get();
+ if (result == null) {
+ result = new HashMap();
+ this.temporaryCache.set(result);
+ }
+ return result;
+ }
/**
* Returns the open ZipFile at the given location. If the ZipFile
* does not yet exist, it is created, opened, and added to the cache
@@ -1075,14 +1280,14 @@ public class JavaModelManager implements ISaveParticipant {
* @exception CoreException If unable to create/open the ZipFile
*/
public ZipFile getZipFile(IPath path) throws CoreException {
-
+
synchronized(this.zipFiles) { // TODO: use PeThreadObject which does synchronization
Thread currentThread = Thread.currentThread();
HashMap map = null;
ZipFile zipFile;
- if ((map = (HashMap)this.zipFiles.get(currentThread)) != null
+ if ((map = (HashMap)this.zipFiles.get(currentThread)) != null
&& (zipFile = (ZipFile)map.get(path)) != null) {
-
+
return zipFile;
}
String fileSystemPath= null;
@@ -1094,24 +1299,24 @@ public class JavaModelManager implements ISaveParticipant {
} else { // internal resource (not an IFile or not existing)
IPath location;
if (file.getType() != IResource.FILE || (location = file.getLocation()) == null) {
- throw new CoreException(new Status(IStatus.ERROR, PHPCore.PLUGIN_ID, -1, Util.bind("file.notFound", path.toString()), null)); //$NON-NLS-1$
+ throw new CoreException(new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Util.bind("file.notFound", path.toString()), null)); //$NON-NLS-1$
}
fileSystemPath= location.toOSString();
}
} else if (!path.isAbsolute()) {
file= root.getFile(path);
if (file == null || file.getType() != IResource.FILE) {
- throw new CoreException(new Status(IStatus.ERROR, PHPCore.PLUGIN_ID, -1, Util.bind("file.notFound", path.toString()), null)); //$NON-NLS-1$
+ throw new CoreException(new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Util.bind("file.notFound", path.toString()), null)); //$NON-NLS-1$
}
IPath location = file.getLocation();
if (location == null) {
- throw new CoreException(new Status(IStatus.ERROR, PHPCore.PLUGIN_ID, -1, Util.bind("file.notFound", path.toString()), null)); //$NON-NLS-1$
+ throw new CoreException(new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Util.bind("file.notFound", path.toString()), null)); //$NON-NLS-1$
}
fileSystemPath= location.toOSString();
} else {
fileSystemPath= path.toOSString();
}
-
+
try {
if (ZIP_ACCESS_VERBOSE) {
System.out.println("(" + currentThread + ") [JavaModelManager.getZipFile(IPath)] Creating ZipFile on " + fileSystemPath ); //$NON-NLS-1$ //$NON-NLS-2$
@@ -1122,17 +1327,22 @@ public class JavaModelManager implements ISaveParticipant {
}
return zipFile;
} catch (IOException e) {
- throw new CoreException(new Status(Status.ERROR, PHPCore.PLUGIN_ID, -1, Util.bind("status.IOException"), e)); //$NON-NLS-1$
+ throw new CoreException(new Status(Status.ERROR, JavaCore.PLUGIN_ID, -1, Util.bind("status.IOException"), e)); //$NON-NLS-1$
}
}
}
-
+ /*
+ * Returns whether there is a temporary cache for the current thread.
+ */
+ public boolean hasTemporaryCache() {
+ return this.temporaryCache.get() != null;
+ }
// public void loadVariablesAndContainers() throws CoreException {
//
-// // backward compatibility, consider persistent property
+// // backward compatibility, consider persistent property
// QualifiedName qName = new QualifiedName(PHPCore.PLUGIN_ID, "variables"); //$NON-NLS-1$
// String xmlString = ResourcesPlugin.getWorkspace().getRoot().getPersistentProperty(qName);
-//
+//
// try {
// if (xmlString != null){
// StringReader reader = new StringReader(xmlString);
@@ -1151,7 +1361,7 @@ public class JavaModelManager implements ISaveParticipant {
// if (!cpElement.getNodeName().equalsIgnoreCase("variables")) { //$NON-NLS-1$
// return;
// }
-//
+//
// NodeList list= cpElement.getChildNodes();
// int length= list.getLength();
// for (int i= 0; i < length; ++i) {
@@ -1160,7 +1370,7 @@ public class JavaModelManager implements ISaveParticipant {
// if (type == Node.ELEMENT_NODE) {
// Element element= (Element) node;
// if (element.getNodeName().equalsIgnoreCase("variable")) { //$NON-NLS-1$
-// variablePut(
+// variablePut(
// element.getAttribute("name"), //$NON-NLS-1$
// new Path(element.getAttribute("path"))); //$NON-NLS-1$
// }
@@ -1172,12 +1382,12 @@ public class JavaModelManager implements ISaveParticipant {
// if (xmlString != null){
// ResourcesPlugin.getWorkspace().getRoot().setPersistentProperty(qName, null); // flush old one
// }
-//
+//
// }
-//
-// // load variables and containers from preferences into cache
-// Preferences preferences = PHPCore.getPlugin().getPluginPreferences();
//
+// // load variables and containers from preferences into cache
+// Preferences preferences = PHPeclipsePlugin.getDefault().getPluginPreferences();
+
// // only get variable from preferences not set to their default
// String[] propertyNames = preferences.propertyNames();
// int variablePrefixLength = CP_VARIABLE_PREFERENCES_PREFIX.length();
@@ -1186,8 +1396,8 @@ public class JavaModelManager implements ISaveParticipant {
// if (propertyName.startsWith(CP_VARIABLE_PREFERENCES_PREFIX)){
// String varName = propertyName.substring(variablePrefixLength);
// IPath varPath = new Path(preferences.getString(propertyName).trim());
-//
-// Variables.put(varName, varPath);
+//
+// Variables.put(varName, varPath);
// PreviousSessionVariables.put(varName, varPath);
// }
// if (propertyName.startsWith(CP_CONTAINER_PREFERENCES_PREFIX)){
@@ -1227,11 +1437,11 @@ public class JavaModelManager implements ISaveParticipant {
public IJavaElementDelta mergeDeltas(Collection deltas) {
if (deltas.size() == 0) return null;
if (deltas.size() == 1) return (IJavaElementDelta)deltas.iterator().next();
-
+
if (DeltaProcessor.VERBOSE) {
System.out.println("MERGING " + deltas.size() + " DELTAS ["+Thread.currentThread()+"]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
-
+
Iterator iterator = deltas.iterator();
IJavaElement javaModel = this.getJavaModel();
JavaElementDelta rootDelta = new JavaElementDelta(javaModel);
@@ -1267,7 +1477,7 @@ public class JavaModelManager implements ISaveParticipant {
else {
return null;
}
- }
+ }
/**
* Returns the info for this element without
@@ -1282,11 +1492,39 @@ public class JavaModelManager implements ISaveParticipant {
*/
public void prepareToSave(ISaveContext context) throws CoreException {
}
-
+
protected void putInfo(IJavaElement element, Object info) {
this.cache.putInfo(element, info);
}
+ /*
+ * Puts the infos in the given map (keys are IJavaElements and values are JavaElementInfos)
+ * in the Java model cache in an atomic way.
+ * First checks that the info for the opened element (or one of its ancestors) has not been
+ * added to the cache. If it is the case, another thread has opened the element (or one of
+ * its ancestors). So returns without updating the cache.
+ */
+ protected synchronized void putInfos(IJavaElement openedElement, Map newElements) {
+ // remove children
+ Object existingInfo = this.cache.peekAtInfo(openedElement);
+ if (openedElement instanceof IParent && existingInfo instanceof JavaElementInfo) {
+ IJavaElement[] children = ((JavaElementInfo)existingInfo).getChildren();
+ for (int i = 0, size = children.length; i < size; ++i) {
+ JavaElement child = (JavaElement) children[i];
+ try {
+ child.close();
+ } catch (JavaModelException e) {
+ // ignore
+ }
+ }
+ }
+ Iterator iterator = newElements.keySet().iterator();
+ while (iterator.hasNext()) {
+ IJavaElement element = (IJavaElement)iterator.next();
+ Object info = newElements.get(element);
+ this.cache.putInfo(element, info);
+ }
+ }
/**
* Reads the build state for the relevant project.
*/
@@ -1297,22 +1535,21 @@ public class JavaModelManager implements ISaveParticipant {
DataInputStream in= new DataInputStream(new BufferedInputStream(new FileInputStream(file)));
try {
String pluginID= in.readUTF();
- if (!pluginID.equals(PHPCore.PLUGIN_ID))
+ if (!pluginID.equals(JavaCore.PLUGIN_ID))
throw new IOException(Util.bind("build.wrongFileFormat")); //$NON-NLS-1$
String kind= in.readUTF();
if (!kind.equals("STATE")) //$NON-NLS-1$
throw new IOException(Util.bind("build.wrongFileFormat")); //$NON-NLS-1$
if (in.readBoolean())
return PHPBuilder.readState(project, in);
-// TODO khartlage temp-del
-// if (JavaBuilder.DEBUG)
-// System.out.println("Saved state thinks last build failed for " + project.getName()); //$NON-NLS-1$
+ if (PHPBuilder.DEBUG)
+ System.out.println("Saved state thinks last build failed for " + project.getName()); //$NON-NLS-1$
} finally {
in.close();
}
} catch (Exception e) {
e.printStackTrace();
- throw new CoreException(new Status(IStatus.ERROR, PHPCore.PLUGIN_ID, Platform.PLUGIN_ERROR, "Error reading last build state for project "+ project.getName(), e)); //$NON-NLS-1$
+ throw new CoreException(new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, Platform.PLUGIN_ERROR, "Error reading last build state for project "+ project.getName(), e)); //$NON-NLS-1$
}
}
return null;
@@ -1326,7 +1563,7 @@ public class JavaModelManager implements ISaveParticipant {
// final String projectName = propertyName.substring(containerPrefixLength, index).trim();
// JavaProject project = (JavaProject)getJavaModelManager().getJavaModel().getJavaProject(projectName);
// final IPath containerPath = new Path(propertyName.substring(index+1).trim());
-//
+//
// if (containerString == null || containerString.equals(CP_ENTRY_IGNORE)) {
// containerPut(project, containerPath, null);
// } else {
@@ -1340,7 +1577,7 @@ public class JavaModelManager implements ISaveParticipant {
// return "Persisted container ["+containerPath+" for project ["+ projectName+"]"; //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
// }
// public int getKind() {
-// return 0;
+// return 0;
// }
// public IPath getPath() {
// return containerPath;
@@ -1370,39 +1607,39 @@ public class JavaModelManager implements ISaveParticipant {
protected void registerJavaModelDelta(IJavaElementDelta delta) {
this.javaModelDeltas.add(delta);
}
-
+
/**
* Remembers the given scope in a weak set
* (so no need to remove it: it will be removed by the garbage collector)
*/
// public void rememberScope(AbstractSearchScope scope) {
// // NB: The value has to be null so as to not create a strong reference on the scope
-// this.scopes.put(scope, null);
+// this.scopes.put(scope, null);
// }
/**
* removeElementChangedListener method comment.
*/
public void removeElementChangedListener(IElementChangedListener listener) {
-
+
for (int i = 0; i < this.elementChangedListenerCount; i++){
-
+
if (this.elementChangedListeners[i].equals(listener)){
-
+
// need to clone defensively since we might be in the middle of listener notifications (#fire)
int length = this.elementChangedListeners.length;
IElementChangedListener[] newListeners = new IElementChangedListener[length];
System.arraycopy(this.elementChangedListeners, 0, newListeners, 0, i);
int[] newMasks = new int[length];
System.arraycopy(this.elementChangedListenerMasks, 0, newMasks, 0, i);
-
+
// copy trailing listeners
int trailingLength = this.elementChangedListenerCount - i - 1;
if (trailingLength > 0){
System.arraycopy(this.elementChangedListeners, i+1, newListeners, i, trailingLength);
System.arraycopy(this.elementChangedListenerMasks, i+1, newMasks, i, trailingLength);
}
-
+
// update manager listener state (#fire need to iterate over original listeners through a local variable to hold onto
// the original ones)
this.elementChangedListeners = newListeners;
@@ -1412,11 +1649,50 @@ public class JavaModelManager implements ISaveParticipant {
}
}
}
-
- protected void removeInfo(IJavaElement element) {
- this.cache.removeInfo(element);
- }
+ /**
+ * Remembers the given scope in a weak set
+ * (so no need to remove it: it will be removed by the garbage collector)
+ */
+// public void rememberScope(AbstractSearchScope scope) {
+// // NB: The value has to be null so as to not create a strong reference on the scope
+// this.searchScopes.put(scope, null);
+// }
+ /*
+ * Removes all cached info for the given element (including all children)
+ * from the cache.
+ * Returns the info for the given element, or null if it was closed.
+ */
+ public synchronized Object removeInfoAndChildren(JavaElement element) throws JavaModelException {
+ Object info = this.cache.peekAtInfo(element);
+ if (info != null) {
+ boolean wasVerbose = false;
+ try {
+ if (VERBOSE) {
+ System.out.println("CLOSING Element ("+ Thread.currentThread()+"): " + element.toStringWithAncestors()); //$NON-NLS-1$//$NON-NLS-2$
+ wasVerbose = true;
+ VERBOSE = false;
+ }
+ element.closing(info);
+ if (element instanceof IParent && info instanceof JavaElementInfo) {
+ IJavaElement[] children = ((JavaElementInfo)info).getChildren();
+ for (int i = 0, size = children.length; i < size; ++i) {
+ JavaElement child = (JavaElement) children[i];
+ child.close();
+ }
+ }
+ this.cache.removeInfo(element);
+ if (wasVerbose) {
+ System.out.println("-> Package cache size = " + this.cache.pkgSize()); //$NON-NLS-1$
+ System.out.println("-> Openable cache filling ratio = " + NumberFormat.getInstance().format(this.cache.openableFillingRatio()) + "%"); //$NON-NLS-1$//$NON-NLS-2$
+ }
+ } finally {
+ JavaModelManager.VERBOSE = wasVerbose;
+ }
+ return info;
+ }
+ return null;
+ }
public void removePerProjectInfo(JavaProject javaProject) {
synchronized(perProjectInfo) { // use the perProjectInfo collection as its own lock
IProject project = javaProject.getProject();
@@ -1426,7 +1702,12 @@ public class JavaModelManager implements ISaveParticipant {
}
}
}
-
+ /*
+ * Resets the temporary cache for newly created elements to null.
+ */
+ public void resetTemporaryCache() {
+ this.temporaryCache.set(null);
+ }
/**
* @see ISaveParticipant
*/
@@ -1437,24 +1718,24 @@ public class JavaModelManager implements ISaveParticipant {
// passed this point, save actions are non trivial
if (context.getKind() == ISaveContext.SNAPSHOT) return;
-
+
// save built state
if (info.triedRead) saveBuiltState(info);
}
-
+
/**
* Saves the built state for the project.
*/
private void saveBuiltState(PerProjectInfo info) throws CoreException {
-// if (JavaBuilder.DEBUG)
-// System.out.println(Util.bind("build.saveStateProgress", info.project.getName())); //$NON-NLS-1$
+ if (PHPBuilder.DEBUG)
+ System.out.println(Util.bind("build.saveStateProgress", info.project.getName())); //$NON-NLS-1$
File file = getSerializationFile(info.project);
if (file == null) return;
long t = System.currentTimeMillis();
try {
DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file)));
try {
- out.writeUTF(PHPCore.PLUGIN_ID);
+ out.writeUTF(JavaCore.PLUGIN_ID);
out.writeUTF("STATE"); //$NON-NLS-1$
if (info.savedState == null) {
out.writeBoolean(false);
@@ -1468,25 +1749,69 @@ public class JavaModelManager implements ISaveParticipant {
} catch (RuntimeException e) {
try {file.delete();} catch(SecurityException se) {}
throw new CoreException(
- new Status(IStatus.ERROR, PHPCore.PLUGIN_ID, Platform.PLUGIN_ERROR,
+ new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, Platform.PLUGIN_ERROR,
Util.bind("build.cannotSaveState", info.project.getName()), e)); //$NON-NLS-1$
} catch (IOException e) {
try {file.delete();} catch(SecurityException se) {}
throw new CoreException(
- new Status(IStatus.ERROR, PHPCore.PLUGIN_ID, Platform.PLUGIN_ERROR,
+ new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, Platform.PLUGIN_ERROR,
Util.bind("build.cannotSaveState", info.project.getName()), e)); //$NON-NLS-1$
}
-// if (JavaBuilder.DEBUG) {
-// t = System.currentTimeMillis() - t;
-// System.out.println(Util.bind("build.saveStateComplete", String.valueOf(t))); //$NON-NLS-1$
-// }
+ if (PHPBuilder.DEBUG) {
+ t = System.currentTimeMillis() - t;
+ System.out.println(Util.bind("build.saveStateComplete", String.valueOf(t))); //$NON-NLS-1$
+ }
+ }
+ private synchronized Map containerClone(IJavaProject project) {
+ Map originalProjectContainers = (Map)this.containers.get(project);
+ if (originalProjectContainers == null) return null;
+ Map projectContainers = new HashMap(originalProjectContainers.size());
+ projectContainers.putAll(originalProjectContainers);
+ return projectContainers;
}
-
/**
* @see ISaveParticipant
*/
public void saving(ISaveContext context) throws CoreException {
-
+
+ // save container values on snapshot/full save
+ Preferences preferences = JavaCore.getPlugin().getPluginPreferences();
+ IJavaProject[] projects = getJavaModel().getJavaProjects();
+ for (int i = 0, length = projects.length; i < length; i++) {
+ IJavaProject project = projects[i];
+ // clone while iterating (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=59638)
+ Map projectContainers = containerClone(project);
+ if (projectContainers == null) continue;
+ for (Iterator keys = projectContainers.keySet().iterator(); keys.hasNext();) {
+ IPath containerPath = (IPath) keys.next();
+// IClasspathContainer container = (IClasspathContainer) projectContainers.get(containerPath);
+ String containerKey = CP_CONTAINER_PREFERENCES_PREFIX+project.getElementName() +"|"+containerPath;//$NON-NLS-1$
+ String containerString = CP_ENTRY_IGNORE;
+// try {
+// if (container != null) {
+// containerString = ((JavaProject)project).encodeClasspath(container.getClasspathEntries(), null, false);
+// }
+// } catch(JavaModelException e){
+// // could not encode entry: leave it as CP_ENTRY_IGNORE
+// }
+ preferences.setDefault(containerKey, CP_ENTRY_IGNORE); // use this default to get rid of removed ones
+ preferences.setValue(containerKey, containerString);
+ }
+ }
+ JavaCore.getPlugin().savePluginPreferences();
+
+// if (context.getKind() == ISaveContext.FULL_SAVE) {
+// // will need delta since this save (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=38658)
+// context.needDelta();
+//
+// // clean up indexes on workspace full save
+// // (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=52347)
+// IndexManager manager = this.indexManager;
+// if (manager != null) {
+// manager.cleanUpIndexes();
+// }
+// }
+
IProject savedProject = context.getProject();
if (savedProject != null) {
if (!JavaProject.hasJavaNature(savedProject)) return; // ignore
@@ -1509,9 +1834,39 @@ public class JavaModelManager implements ISaveParticipant {
if (vStats != null) {
IStatus[] stats= new IStatus[vStats.size()];
vStats.toArray(stats);
- throw new CoreException(new MultiStatus(PHPCore.PLUGIN_ID, IStatus.ERROR, stats, Util.bind("build.cannotSaveStates"), null)); //$NON-NLS-1$
+ throw new CoreException(new MultiStatus(JavaCore.PLUGIN_ID, IStatus.ERROR, stats, Util.bind("build.cannotSaveStates"), null)); //$NON-NLS-1$
}
}
+ /**
+ * @see ISaveParticipant
+ */
+// public void saving(ISaveContext context) throws CoreException {
+//
+// IProject savedProject = context.getProject();
+// if (savedProject != null) {
+// if (!JavaProject.hasJavaNature(savedProject)) return; // ignore
+// PerProjectInfo info = getPerProjectInfo(savedProject, true /* create info */);
+// saveState(info, context);
+// return;
+// }
+//
+// ArrayList vStats= null; // lazy initialized
+// for (Iterator iter = perProjectInfo.values().iterator(); iter.hasNext();) {
+// try {
+// PerProjectInfo info = (PerProjectInfo) iter.next();
+// saveState(info, context);
+// } catch (CoreException e) {
+// if (vStats == null)
+// vStats= new ArrayList();
+// vStats.add(e.getStatus());
+// }
+// }
+// if (vStats != null) {
+// IStatus[] stats= new IStatus[vStats.size()];
+// vStats.toArray(stats);
+// throw new CoreException(new MultiStatus(JavaCore.PLUGIN_ID, IStatus.ERROR, stats, Util.bind("build.cannotSaveStates"), null)); //$NON-NLS-1$
+// }
+// }
/**
* Record the order in which to build the java projects (batch build). This order is based
@@ -1521,10 +1876,10 @@ public class JavaModelManager implements ISaveParticipant {
// optional behaviour
// possible value of index 0 is Compute
- if (!PHPCore.COMPUTE.equals(PHPCore.getOption(PHPCore.CORE_JAVA_BUILD_ORDER))) return; // cannot be customized at project level
-
+ if (!JavaCore.COMPUTE.equals(JavaCore.getOption(JavaCore.CORE_JAVA_BUILD_ORDER))) return; // cannot be customized at project level
+
if (javaBuildOrder == null || javaBuildOrder.length <= 1) return;
-
+
IWorkspace workspace = ResourcesPlugin.getWorkspace();
IWorkspaceDescription description = workspace.getDescription();
String[] wksBuildOrder = description.getBuildOrder();
@@ -1586,7 +1941,7 @@ public class JavaModelManager implements ISaveParticipant {
}
public void shutdown () {
-// TODO khartlage temp-del
+// TODO temp-del
// if (this.deltaProcessor.indexManager != null){ // no more indexing
// this.deltaProcessor.indexManager.shutdown();
// }
@@ -1615,24 +1970,24 @@ public class JavaModelManager implements ISaveParticipant {
public void stopDeltas() {
this.isFiring= false;
}
-
+
/**
* Update Java Model given some delta
*/
-// public void updateJavaModel(IJavaElementDelta customDelta) {
-//
-// if (customDelta == null){
-// for (int i = 0, length = this.javaModelDeltas.size(); i < length; i++){
-// IJavaElementDelta delta = (IJavaElementDelta)this.javaModelDeltas.get(i);
-// this.modelUpdater.processJavaDelta(delta);
-// }
-// } else {
-// this.modelUpdater.processJavaDelta(customDelta);
-// }
-// }
+ public void updateJavaModel(IJavaElementDelta customDelta) {
+
+ if (customDelta == null){
+ for (int i = 0, length = this.javaModelDeltas.size(); i < length; i++){
+ IJavaElementDelta delta = (IJavaElementDelta)this.javaModelDeltas.get(i);
+ this.modelUpdater.processJavaDelta(delta);
+ }
+ } else {
+ this.modelUpdater.processJavaDelta(customDelta);
+ }
+ }
+
-
public static IPath variableGet(String variableName){
return (IPath)Variables.get(variableName);
}
@@ -1647,10 +2002,10 @@ public class JavaModelManager implements ISaveParticipant {
}
return result;
}
-
- public static void variablePut(String variableName, IPath variablePath){
- // update cache - do not only rely on listener refresh
+ public static void variablePut(String variableName, IPath variablePath){
+
+ // update cache - do not only rely on listener refresh
if (variablePath == null) {
Variables.remove(variableName);
PreviousSessionVariables.remove(variableName);
@@ -1661,12 +2016,63 @@ public class JavaModelManager implements ISaveParticipant {
// do not write out intermediate initialization value
if (variablePath == JavaModelManager.VariableInitializationInProgress){
return;
- }
- Preferences preferences = PHPCore.getPlugin().getPluginPreferences();
+ }
+ Preferences preferences = JavaCore.getPlugin().getPluginPreferences();
String variableKey = CP_VARIABLE_PREFERENCES_PREFIX+variableName;
String variableString = variablePath == null ? CP_ENTRY_IGNORE : variablePath.toString();
preferences.setDefault(variableKey, CP_ENTRY_IGNORE); // use this default to get rid of removed ones
preferences.setValue(variableKey, variableString);
- PHPCore.getPlugin().savePluginPreferences();
+ JavaCore.getPlugin().savePluginPreferences();
+ }
+ /*
+ * Returns all the working copies which have the given owner.
+ * Adds the working copies of the primary owner if specified.
+ * Returns null if it has none.
+ */
+ public ICompilationUnit[] getWorkingCopies(WorkingCopyOwner owner, boolean addPrimary) {
+ synchronized(perWorkingCopyInfos) {
+ ICompilationUnit[] primaryWCs = addPrimary && owner != DefaultWorkingCopyOwner.PRIMARY
+ ? getWorkingCopies(DefaultWorkingCopyOwner.PRIMARY, false)
+ : null;
+ Map workingCopyToInfos = (Map)perWorkingCopyInfos.get(owner);
+ if (workingCopyToInfos == null) return primaryWCs;
+ int primaryLength = primaryWCs == null ? 0 : primaryWCs.length;
+ int size = workingCopyToInfos.size(); // note size is > 0 otherwise pathToPerWorkingCopyInfos would be null
+ ICompilationUnit[] result = new ICompilationUnit[primaryLength + size];
+ if (primaryWCs != null) {
+ System.arraycopy(primaryWCs, 0, result, 0, primaryLength);
+ }
+ Iterator iterator = workingCopyToInfos.values().iterator();
+ int index = primaryLength;
+ while(iterator.hasNext()) {
+ result[index++] = ((JavaModelManager.PerWorkingCopyInfo)iterator.next()).getWorkingCopy();
+ }
+ return result;
+ }
+ }
+
+ /*
+ * A HashSet that contains the IJavaProject whose classpath is being resolved.
+ */
+ private ThreadLocal classpathsBeingResolved = new ThreadLocal();
+
+ private HashSet getClasspathBeingResolved() {
+ HashSet result = (HashSet) this.classpathsBeingResolved.get();
+ if (result == null) {
+ result = new HashSet();
+ this.classpathsBeingResolved.set(result);
+ }
+ return result;
+ }
+ public boolean isClasspathBeingResolved(IJavaProject project) {
+ return getClasspathBeingResolved().contains(project);
+ }
+
+ public void setClasspathBeingResolved(IJavaProject project, boolean classpathIsResolved) {
+ if (classpathIsResolved) {
+ getClasspathBeingResolved().add(project);
+ } else {
+ getClasspathBeingResolved().remove(project);
+ }
}
}