Bug 20931 - Need an API to reload the classpath from the file
Summary: Need an API to reload the classpath from the file
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 2.0   Edit
Hardware: All All
: P3 enhancement (vote)
Target Milestone: 3.0 M2   Edit
Assignee: Philipe Mulet CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2002-06-24 23:43 EDT by Ritchie Schacher CLA
Modified: 2003-07-16 09:42 EDT (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Ritchie Schacher CLA 2002-06-24 23:43:21 EDT
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
Comment 1 Philipe Mulet CLA 2002-06-25 05:44:41 EDT
This workaround is actually the right way to go. Might add an API post-2.0.
Comment 2 Ritchie Schacher CLA 2003-06-04 13:05:33 EDT
In 2.1.1, the close and reopen trick is no longer working.
Comment 3 Ritchie Schacher CLA 2003-06-04 13:14:10 EDT
This is a regression from 2.0, and causes a failure in our product.
Comment 4 Philipe Mulet CLA 2003-06-05 04:59:22 EDT
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.

Comment 5 Ritchie Schacher CLA 2003-06-05 09:34:38 EDT
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.
Comment 6 Philipe Mulet CLA 2003-06-05 10:49:01 EDT
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.
Comment 7 Ritchie Schacher CLA 2003-06-05 10:58:33 EDT
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.
Comment 8 Philipe Mulet CLA 2003-06-05 11:18:35 EDT
The latter sounds suspicious. This seems to indicate that a .classpath file 
change could be missed. Can you provide steps to reproduce ?
Comment 9 Ritchie Schacher CLA 2003-06-05 11:35:50 EDT
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.
Comment 10 Philipe Mulet CLA 2003-06-05 13:09:13 EDT
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;
Comment 11 Ritchie Schacher CLA 2003-06-05 13:21:20 EDT
Thanks, I will try the hack.  The separate touch outside the operation does 
indeed refresh as you would expect.
Comment 12 Ritchie Schacher CLA 2003-06-05 13:41:06 EDT
Hack works, thanks.
Comment 13 David Audel CLA 2003-07-16 09:42:34 EDT
Verified.