Bug 337415 - External folders project is not created
Summary: External folders project is not created
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.7   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: 3.7 M7   Edit
Assignee: Jay Arthanareeswaran CLA
QA Contact:
URL:
Whiteboard:
Keywords:
: 340629 (view as bug list)
Depends on:
Blocks: 340629 343509
  Show dependency tree
 
Reported: 2011-02-17 06:26 EST by Krzysztof Daniel CLA
Modified: 2011-04-25 06:08 EDT (History)
5 users (show)

See Also:
satyam.kandula: review+


Attachments
Workspace for recreation steps (59.73 KB, application/x-zip-compressed)
2011-02-17 06:26 EST, Krzysztof Daniel CLA
no flags Details
Proposed Patch (2.28 KB, patch)
2011-04-13 07:04 EDT, Jay Arthanareeswaran CLA
no flags Details | Diff
Updated patch (4.51 KB, patch)
2011-04-15 03:42 EDT, Jay Arthanareeswaran CLA
no flags Details | Diff
proposed patch (3.99 KB, text/plain)
2011-04-15 09:45 EDT, Satyam Kandula CLA
no flags Details
Updated patch (4.47 KB, patch)
2011-04-15 10:38 EDT, Jay Arthanareeswaran CLA
no flags Details | Diff
Patch (2.55 KB, patch)
2011-04-18 07:56 EDT, Jay Arthanareeswaran CLA
no flags Details | Diff
Improved patch (3.95 KB, patch)
2011-04-19 04:34 EDT, Jay Arthanareeswaran CLA
no flags Details | Diff
One more patch (4.03 KB, patch)
2011-04-19 04:47 EDT, Jay Arthanareeswaran CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Krzysztof Daniel CLA 2011-02-17 06:26:52 EST
Created attachment 189164 [details]
Workspace for recreation steps

When the preferences and the project are imported using ANT script, the external folders project is not created causing potentially dangerous behavior (f.e. no delta can be computed, so each build is a full build).

The steps to reproduce the behavior are:
1. Import the projects from attached zip file
2. Inside the Data project there are two launch configurations.
3. Execute the "Headless Import"
4. Refresh the Data project. runtimeData folder contains new workspace, check in the .metadata/.plugins/org.eclipse.jdt.core if the external folders project exists.

Two other projects are ant tasks responsible for loading the preferences and importing the project. The second launch configuration ("Verification") launches Eclipse which uses the same workspace as the headless one, so it is possible to check if the classpath variable has been correctly loaded.
Comment 1 Krzysztof Daniel CLA 2011-02-17 06:35:08 EST
I have noticed that when you launch Eclipse for the next time, you get a message that the workspace did not quit correctly. Maybe this behavior is resources fault.
Comment 2 Krzysztof Daniel CLA 2011-02-18 05:03:18 EST
Jayaprakash,
if you could just write some clues, I'd be happy to assist you on investigating this bug.
Comment 3 Jay Arthanareeswaran CLA 2011-02-18 06:12:35 EST
Actually, I am having trouble setting up the given workspace. Getting the following errors:

Unbound classpath variable: 'DB2JDBC' in project 'TestProject'	
Unbound classpath variable: 'SQLJ_JAR' in project 'TestProject'	

And looks like the required JARs are inside the ZIP.
Comment 4 Krzysztof Daniel CLA 2011-02-18 06:23:04 EST
You should not import the TestProject. It is held in Data project and it is used for imports, but in the workspace for reproduction it is not a top-level project. You should import two projects with ant tasks and one with data.
Comment 5 Jay Arthanareeswaran CLA 2011-02-18 09:35:05 EST
I can reproduce this bug with eclipse build I20110127-2034, however not consistently. Interestingly, I didn't manage to reproduce this even once with HEAD.

Of course, you can take a stab at it. The external project is handled by ExternalFoldersManager. The project is created at the first request to create a link folder to an external path. A good starting point for debug is perhaps ExternalFoldersManager#createLinkFolder(IPath, boolean, IProgressMonitor), which gets called either when there is a resource change event DeltaProcessor#resourceChanged(IResourceChangeEvent) or a classpath change ChangeClasspathOperation#classpathChanged(ClasspathChange, boolean).

These are under project: org.eclipse.jdt.core
Comment 6 Krzysztof Daniel CLA 2011-02-18 10:25:44 EST
(In reply to comment #5)
> I can reproduce this bug with eclipse build I20110127-2034, however not
> consistently. Interestingly, I didn't manage to reproduce this even once with
> HEAD.
I will try to reproduce it with HEAD.

> Of course, you can take a stab at it. The external project is handled by
> ExternalFoldersManager. The project is created at the first request to create a
> link folder to an external path. A good starting point for debug is perhaps
> ExternalFoldersManager#createLinkFolder(IPath, boolean, IProgressMonitor),
> which gets called either when there is a resource change event
> DeltaProcessor#resourceChanged(IResourceChangeEvent) or a classpath change
> ChangeClasspathOperation#classpathChanged(ClasspathChange, boolean).
> These are under project: org.eclipse.jdt.core

I have already checked that. Those methods are not called, because the project is not yet accessible or the resource tree is locked (it looks like the delta is recorded for further processing, however, I do not know this code well enough to say exactly).
Comment 7 Jay Arthanareeswaran CLA 2011-02-22 04:18:59 EST
The issue here is that the JDT isn't aware of the existence of the imported project. I think copying all the project contents over and then creating a project along with java nature should solve the problem.

You can create the project with something like this:

IProjectDescription desc = 
              project.getWorkspace().newProjectDescription(project.getName());

desc.setNatureIds(new String[] {JavaCore.NATURE_ID});
project.create(desc, monitor);

The key here is the Java nature.
Also, you can look at the following code for importing an existing project.

org.eclipse.ui.internal.wizards.datatransfer.WizardProjectsImportPage.createExistingProject()

Let me know if this helps.
Comment 8 Krzysztof Daniel CLA 2011-02-23 08:23:44 EST
Unfortunately setting explicitly the java nature did not help (although I could not accept that workaround, because you cannot assume that every project has a java nature).

The test code is based on class that you referenced. This is the problem - that in the UI everything works fine, and in headless mode - no.
Comment 9 Krzysztof Daniel CLA 2011-02-23 08:32:05 EST
As I have said before - this looks like a timing issue.

Adding 10s sleep at the end of the task causes the folder to be created.
Comment 10 Krzysztof Daniel CLA 2011-02-28 10:41:10 EST
Ok, I guess that if Eclipse (JDT) is being shut down, it ignores deltas. Is there anything I could wait for instead of adding Thread.sleep to be sure that all deltas are processed correctly?
Comment 11 Jay Arthanareeswaran CLA 2011-02-28 23:39:49 EST
(In reply to comment #10)
> Ok, I guess that if Eclipse (JDT) is being shut down, it ignores deltas. Is
> there anything I could wait for instead of adding Thread.sleep to be sure that
> all deltas are processed correctly?

You can look at the following two helper methods as they might be useful.

org.eclipse.jdt.core.tests.model.AbstractJavaModelTests#waitForManualRefresh()
org.eclipse.jdt.core.tests.model.AbstractJavaModelTests#waitForAutoBuild()

At this point, since we are convinced that this is not an eclipse bug, I am closing it. Should you require further help, you can post your questions on eclipse forum.
Comment 12 Jay Arthanareeswaran CLA 2011-02-28 23:41:17 EST
Marking as RESOLVED.
Comment 13 Satyam Kandula CLA 2011-03-07 06:41:34 EST
Verified for 3.7M6
Comment 14 Dani Megert CLA 2011-03-22 03:49:29 EDT
*** Bug 340629 has been marked as a duplicate of this bug. ***
Comment 15 Dani Megert CLA 2011-03-22 03:50:34 EDT
Srikanth, please also also take a closer look at this.
Comment 16 Krzysztof Daniel CLA 2011-03-22 04:03:38 EDT
After longer consideration, I think this issue is JDT weakness. The external
folders project is created in this scenario in response to build event, which
is not guaranteed to happen. More over, only the first build event after import
carries the delta. If the Eclipse is closed, if it crashes or something, then
subsequents build events will not create the project.
Comment 17 Krzysztof Daniel CLA 2011-04-08 11:22:18 EDT
reopening as per last comment
Comment 18 Krzysztof Daniel CLA 2011-04-11 03:39:34 EDT
Following code never creates the external project (try catches removed for the sake of readability):

IWorkspaceRunnable runnable = new IWorkspaceRunnable(){
    public void run(IProgressMonitor monitor) throws CoreException {
        JavaCore.initializeAfterLoad(monitor);
        final IProjectDescription description = workspace.newProjectDescription(projectName);
        description.setLocation(new Path(projectLocation));
				
        final IProject project = workspace.getRoot().getProject(projectName);
        project.create(description, monitor);
	project.open(IResource.NONE, monitor);
    }
};
workspace.run(runnable, monitor);
ResourcesPlugin.getWorkspace().getRoot().refreshLocal(IResource.DEPTH_INFINITE, monitor);
Job.getJobManager().join(ResourcesPlugin.FAMILY_AUTO_BUILD, null);

But a few tweaks, and it creates the external project always (project.open has different refresh flag, the separate refresh local is removed):

IWorkspaceRunnable runnable = new IWorkspaceRunnable(){
    public void run(IProgressMonitor monitor) throws CoreException {
        JavaCore.initializeAfterLoad(monitor);
        final IProjectDescription description = workspace.newProjectDescription(projectName);
        description.setLocation(new Path(projectLocation));
				
	final IProject project = workspace.getRoot().getProject(projectName);
	project.create(description, monitor);
	project.open(IResource.BACKGROUND_REFRESH, monitor);
    }
};
workspace.run(runnable, monitor);
Job.getJobManager().join(ResourcesPlugin.FAMILY_AUTO_BUILD, null);
Comment 19 Jay Arthanareeswaran CLA 2011-04-13 03:11:19 EDT
(In reply to comment #18)
> Following code never creates the external project (try catches removed for the
> sake of readability):

Surprisingly, the external folders project is created in both cases. But since I can reproduce the bug as described in comment #0, I will see what we can do to ensure the creation of the project always.
Comment 20 Jay Arthanareeswaran CLA 2011-04-13 07:04:58 EDT
Created attachment 193147 [details]
Proposed Patch

Considering the inconsistencies surrounding the creation of the external folder project, and that we end up creating one most times, I think the better place to create the project (of course, if it doesn't already exist) is the JavaCore#initializeAfterLoad().

The patch has just that one change and may require some minor changes.

Christopher, can you please check if this works for the test case in comment #18?
Comment 21 Jay Arthanareeswaran CLA 2011-04-13 07:06:25 EDT
Satyam, please take a look at the patch and let me know if you see any problems with it. The fix is very simple and should keep most people happy considering we are at M7.
Comment 22 Krzysztof Daniel CLA 2011-04-14 04:11:32 EDT
I am afraid this patch will not work as expected. External project created in that way has always clean .project. While the code that somehow prevents Eclipse from closing creates a .project which has the link resources inside:

<linkedResources>
		<link>
			<name>.link0</name>
			<type>2</type>
			<location>C:/test</location>
		</link>
</linkedResources>

The problem is that during headless import of projects the resource tree is locked and all deltas are recorded. But then, Eclipse is shut down, and processing of deltas never happens because of optimization (normally it makes a lot of sense to not process deltas on shutdown).

I think that it would be much more convenient to have some sort of wait method which will guarantee that all events has been processed.
Comment 23 Jay Arthanareeswaran CLA 2011-04-14 11:11:33 EDT
Thanks for the update, Christopher. 

I am not very sure if making it wait till event processing complete will work always. For instance, the event listener itself might fail. We need something that recovers even if something goes wrong, at least when the workspace (and project) is opened again. 

Another approach we considered was to try creating the .project during JavaCore initialization and create the links during classpath resolution. But as has been recorded in bug 320618, comment #2, it has it's problems too. I am still investigating other options and will keep you updated soon.
Comment 24 Jay Arthanareeswaran CLA 2011-04-15 03:42:50 EDT
Created attachment 193327 [details]
Updated patch

Unlike the previous patch, this also takes care of missing external folder links, if any, during JavaCore init. 
We did have some code to do this already inside JavaCore#initializeAfterLoad() but it had three issues:

1. This doesn't take care of source attachment paths as external folders.
2. This code was not having any effect at all for reasons mentioned in bug 320618, comment #2 - The getFolders might return a result even though it's present only in the cache and NOT in the .project file.
3. The external folders change, if any, were added to the delta processing state. This means the changes will be persisted if and only if there is a next resource change or classpath change.

There will be a bit of additional effort from the JavaCore#initializeAfterLoad() with the new patch, but only for the first load after we encounter this bug.

Satyam, what do you think?
And Christopher, do think this will work for you?
Comment 25 Satyam Kandula CLA 2011-04-15 07:28:24 EDT
Jay, 
The patch works for me and I think fixing the link folders when the IDE comes up is the best idea.  

Instead of going through updateExternalFoldersIfNecessary, can we just check for pendingFolders and call the function to create the link folders? With the new check for source attachments, I am afraid of another performance regression in our tests that we had seen in bug 338649. We could keep the performance impact less by this change. However, I am not sure if this works. 

If it is not possible to directly call the link folders, then look at the following comments. 

1. manager.deltaState.addExternalFolderChange(javaProject, null/*act as if all external folders were new*/) does work but works only after a build. As in this testcase, there are no files, build is not getting triggered and hence the problem. If I force a build, I could see the link getting created. So, this change may not be required. 

2. For the new checks you had added for the source attachment, I think we could add one additional check of if (!needExternalFolderCreation).
Comment 26 Satyam Kandula CLA 2011-04-15 09:45:01 EDT
Created attachment 193372 [details]
proposed patch
Comment 27 Satyam Kandula CLA 2011-04-15 09:48:25 EDT
(In reply to comment #26)
Jay, Here is a patch to demonstrate the changes that I am proposing. When I put the comment initially I missed out adding the folder and got it after talking to you. I think this should work. This test case works but I have not run all the tests.
Comment 28 Jay Arthanareeswaran CLA 2011-04-15 10:38:46 EDT
Created attachment 193380 [details]
Updated patch

Thanks for the patch, Satyam. I have made one small correction to the patch and attaching here.

Christopher, we have tested this fixes the reported problem. It would be nice if you can confirm that too.
Comment 29 Krzysztof Daniel CLA 2011-04-15 12:02:38 EDT
My initial tests went fine. I will test the patch in 3.4 environment on Monday.
Comment 30 Krzysztof Daniel CLA 2011-04-18 05:21:54 EDT
The patch works.
Comment 31 Jay Arthanareeswaran CLA 2011-04-18 06:10:50 EDT
Thanks for the confirmation, Christopher.
Released the fix in HEAD for 3.7 M7.
Comment 32 Dani Megert CLA 2011-04-18 07:01:04 EDT
The fix now always creates the external folders project. That's not good. If I never created an external class folder (true for most users) I don't want to pay. Even if minimal, this also slows down start up / initializeAfterLoad(...).
Comment 33 Jay Arthanareeswaran CLA 2011-04-18 07:56:46 EDT
Created attachment 193481 [details]
Patch

With this patch, we create the external folders project only if required.

Dani, any comments?
Comment 34 Srikanth Sankaran CLA 2011-04-19 01:21:56 EDT
Satyam, please review the latest patch to make sure it addresses
Dani's concern while still being a good fix for the original issue,
Thanks.
Comment 35 Jay Arthanareeswaran CLA 2011-04-19 04:34:44 EDT
Created attachment 193554 [details]
Improved patch

This patch has some improvements over the previous ones. Added a log message in case of an error processing external folders; Code trying to create the external folder project has been moved outside the loop etc.
Comment 36 Jay Arthanareeswaran CLA 2011-04-19 04:47:56 EDT
Created attachment 193555 [details]
One more patch

Added one more log statement which was missing in the previous patch.
Comment 37 Satyam Kandula CLA 2011-04-19 04:51:03 EDT
This patch is good. 
+1
Comment 38 Jay Arthanareeswaran CLA 2011-04-19 12:18:26 EDT
Released the improvements in HEAD for 3.7 M7.
Comment 39 Dani Megert CLA 2011-04-21 05:22:13 EDT
(In reply to comment #33)
> Created attachment 193481 [details] [diff]
> Patch
> 
> With this patch, we create the external folders project only if required.
> 
> Dani, any comments?

Looks better now ;-)
Comment 40 Satyam Kandula CLA 2011-04-25 06:08:56 EDT
Verified for 3.7M7 using build I20110421-1800