Community
Participate
Working Groups
I have a scenario where the .classpath file gets overwritten as part of an import operation. I then need to be able to query the classpath from the IJavaProject, and perhaps make more modifications. The problem is that the old classpath is still in memory. I'd like an api to force a reload. To workaround the limitation, my code currently closes the IJavaProject and then opens it again. This feels like it might be overkill. Thanks
This workaround is actually the right way to go. Might add an API post-2.0.
In 2.1.1, the close and reopen trick is no longer working.
This is a regression from 2.0, and causes a failure in our product.
We moved the classpath cache from the element info to separate entities (per project infos) which aren't flushed when closing a project. Isn't the classpath modification properly detected during the import process ? Normally, a change to the .classpath file is reconciled, and the in-memory classpath would be updated accordingly.
It appears not to be. The .classpath is being overwritten inside a WorkspaceModifyOperation. Within the same operation, it has to be reloaded. The code we have is: <br> IJavaProject javaProj = ... javaProj.close(); javaProj.open(new NullProgressMonitor()); if you then get the raw classpath from the Java project, it does not have the entries in the newer .classpath file.
I see. Indeed, the classpath change is only detected when we get notified (at the end of the operation). Until this occurs, the in-memory path is kept. Can't you separate the two operations ? If not, we will have to provide something which triggers the reload.
Separating this into two operations would involve significant changes to a codebase that is already tested and was previously working. It is also important that for an import we have one continuous operation to avoid flashing in the wizard and to keep one cycle through the progress monitor. Therefore I don't think this is an option. Also, I did not mention that for web projects, we do not modify the classpath within the operation, but nonetheless, after the operation is complete, both the package explorer and the Java build path properties show the old classpath. If I touch the file, the classpath then refreshes. This was never a problem in older versions, but if I have the API for reload, then I can use it for this scenario as well.
The latter sounds suspicious. This seems to indicate that a .classpath file change could be missed. Can you provide steps to reproduce ?
This should do it: Within an operation, replace a .classpath file with the contents of another, using something similar to the following: InputStream inputStream = new ByteArrayInputStream(contents, 0, contents.length); try { if (!file.exists()) { file.create(inputStream, false, null); } else { if (!file.isLocal(IResource.DEPTH_ONE) || !file.isSynchronized (IResource.DEPTH_ONE)) { file.refreshLocal(IResource.DEPTH_ONE, progressMonitor); } file.setContents(inputStream, force, keepHistory, progressMonitor); } } that should be it. If the classpath does indeed refresh for you, then there is something else missing in this simple test case. For the original problem, within this same operation, close and reopen the IJavaProject, and read the rawClasspath. You should see the old values.
I got that case, but was wondering if you were saying that a separate touch of the .classpath file (outside operation) did not work either. Anyway, added IJavaProject#forceClasspathReload(IProgressMonitor). Fixed into 3.0M2 stream. For the current time being, this hack could be enough, assuming p1 is your project. p1.close(); JavaModelManager.PerProjectInfo perProjectInfo = JavaModelManager.getJavaModelManager() .getPerProjectInfo(p1.getProject(), true); perProjectInfo.classpath = null; perProjectInfo.lastResolvedClasspath = null;
Thanks, I will try the hack. The separate touch outside the operation does indeed refresh as you would expect.
Hack works, thanks.
Verified.