Bug 142330 - [CommonNavigator][Java] Java content provider should not add resources back
Summary: [CommonNavigator][Java] Java content provider should not add resources back
Status: RESOLVED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: UI (show other bugs)
Version: 3.2   Edit
Hardware: PC Windows XP
: P3 major with 1 vote (vote)
Target Milestone: 3.3 M7   Edit
Assignee: Michael D. Elder CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks: 150404
  Show dependency tree
 
Reported: 2006-05-17 16:01 EDT by Michael Valenta CLA
Modified: 2007-04-26 13:19 EDT (History)
4 users (show)

See Also:


Attachments
Patches JavaNavigatorContentProvider to filter only Java Projects (2.23 KB, patch)
2006-07-26 11:52 EDT, Michael D. Elder CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Michael Valenta CLA 2006-05-17 16:01:19 EDT
The Java content provider for the Project Explorer overrides the Resources content provider. What it does is remove all resources from the children of IWorkspaceRoot and then adds back either Java projects or Resource projects. The problem is that there may be other content extensions that have replaced resource projects with model projects and these projects will get added back resulting in what appears like duplicate entries in the Project Explorer.

The algorithm in the getPipelinedElements should be:

1) Remove all projects that have the Java nature
2) Add all Java projects to the result
Comment 1 Michael D. Elder CLA 2006-05-17 16:28:12 EDT
Is this a change you need for 3.2? Or 3.2.1? 

I think the change is safe to make.
Comment 2 Michael Valenta CLA 2006-05-17 16:38:59 EDT
I don't need it at all. I just noticed the behavior when working on an model example that uses the Project Explorer. Given that most of the current clients are built on top of the Java content provider anyway, it's probably not a stop-ship for 3.2. I'll leave it up to you (and JDT/UI) to decide whether the fix should be in 3.2.1 or wait until 3.3.
Comment 3 Michael D. Elder CLA 2006-05-17 16:54:22 EDT
In that case, I'd recommend a fix for 3.2.1.
Comment 4 Michael D. Elder CLA 2006-07-26 11:52:44 EDT
Created attachment 46827 [details]
Patches JavaNavigatorContentProvider to filter only Java Projects
Comment 5 Michael D. Elder CLA 2006-07-27 15:05:45 EDT
Martin -- would you review for release to M20060802?
Comment 6 Martin Aeschlimann CLA 2006-07-28 04:33:06 EDT
I don't think that the patch works for Michael's example. You should only add back Java projects, but children (=getElements(input)) contains resource and Java projects.
The correct implementation to iterate through all elements and one by one replace IProjects that have a Java nature.
It could also be that a content extensions replaced a IProject with Java nature. So this project shouldn't show up again.
Comment 7 Michael D. Elder CLA 2006-08-15 14:21:01 EDT
If this isn't a serious problem, I'm inclined to defer it to 3.3; I know of no extension that is affected by this behavior. 

Michael V and Martin -- are you okay with this?
Comment 8 Martin Aeschlimann CLA 2006-08-16 04:34:39 EDT
I wouldn't mind seeing this fixed as it seems to me that getPipelinedChildren is fundamentally broken.
Comment 9 Michael D. Elder CLA 2006-08-16 10:46:20 EDT
Originally, JDT/UI wanted their extension to return Java and Resource content. In the WTP version, there was a split; one extension returned resources, and one extension returned only Java elements. 

To change getChildren() to only return Java elements is a pretty big change for this timeframe; if I misunderstood your original comments, could you rephrase?
Comment 10 Martin Aeschlimann CLA 2006-08-16 10:57:36 EDT
I'm only concerned about the method 'getPipelinedElements'. I'm not sure where and if it is used. But if I understand right, its implementation should iterate through all 'currentChildren' and test each if it is of type IProject and if it's nature is a Java nature. If that's the case, it should be replaced it by the corresponding Java element.
That leaves all non-java projects and other projects of unknown type as they are.
Comment 11 Franck Mising name CLA 2006-09-05 10:56:27 EDT
I am seeing a problem with the JavaNavigatorContentProvider that I think is related to this one, so I'll just post a comment here first - please let me know if this should be a new bug.

I am adding a model content provider to the project explorer for projects of a given nature. I am overriding the resource content provider, replacing projects with my Foo nature and their resources with my model elements.

The pb I see has to do with resource changes: the java navigator content provider is posting adds (postAdd, see stack traces below) for resources, instead of relying on intercept add to intercept the changes posted by the resource content provider. It does so not only for java resources (which I suspect it shouldn't), but also for non-java resources (e.g. folder in a project that doesn't have a java nature).

The result is that the viewer.add method (and thus the interceptAdd methods of overriding extensions) is called twice for each add.
Note that the same is probably true of most other resource change event types.

Here are 3 stack traces that demonstrate the pb. They have been obtained by opening both the (legacy) Navigator view and the project explorer view, and creating a new folder under a Foo (non-java) project using the Navigator popup menu:

trace1: JavaNavigatorContentProvider posts an add:
------------------------------------------------------
JavaNavigatorContentProvider(PackageExplorerContentProvider).postAdd(Object, Object) line: 623	
JavaNavigatorContentProvider.postAdd(Object, Object) line: 221	
JavaNavigatorContentProvider(PackageExplorerContentProvider).processResourceDelta(IResourceDelta, Object) line: 549	
JavaNavigatorContentProvider(PackageExplorerContentProvider).processResourceDeltas(IResourceDelta[], Object) line: 579	
JavaNavigatorContentProvider(PackageExplorerContentProvider).processResourceDelta(IResourceDelta, Object) line: 556	
JavaNavigatorContentProvider(PackageExplorerContentProvider).processResourceDeltas(IResourceDelta[], Object) line: 579	
JavaNavigatorContentProvider(PackageExplorerContentProvider).processResourceDelta(IResourceDelta, Object) line: 556	
JavaNavigatorContentProvider(PackageExplorerContentProvider).processResourceDeltas(IResourceDelta[], Object) line: 579	
JavaNavigatorContentProvider(PackageExplorerContentProvider).processDelta(IJavaElementDelta) line: 422	
JavaNavigatorContentProvider(PackageExplorerContentProvider).elementChanged(ElementChangedEvent) line: 105	
DeltaProcessor$3.run() line: 1448	
SafeRunner.run(ISafeRunnable) line: 37	
DeltaProcessor.notifyListeners(IJavaElementDelta, int, IElementChangedListener[], int[], int) line: 1438	
DeltaProcessor.firePostChangeDelta(IJavaElementDelta, IElementChangedListener[], int[], int) line: 1286	
DeltaProcessor.fire(IJavaElementDelta, int) line: 1265	
DeltaProcessor.resourceChanged(IResourceChangeEvent) line: 1824	
DeltaProcessingState.resourceChanged(IResourceChangeEvent) line: 444	
NotificationManager$2.run() line: 280	
SafeRunner.run(ISafeRunnable) line: 37	
NotificationManager.notify(ResourceChangeListenerList$ListenerEntry[], IResourceChangeEvent, boolean) line: 274	
NotificationManager.broadcastChanges(ElementTree, ResourceChangeEvent, boolean) line: 148	
Workspace.broadcastPostChange() line: 256	

---------------------------------
trace 2: JavaNavigatorContentProvider interceptAdd is called as a result of #1:
----------------------------------
JavaNavigatorContentProvider.interceptAdd(PipelinedShapeModification) line: 146	
SafeDelegateTreeContentProvider.interceptAdd(PipelinedShapeModification) line: 224	
NavigatorPipelineService.pipelineInterceptAdd(PipelinedShapeModification, ContributorTrackingSet, INavigatorContentDescriptor) line: 95	
NavigatorPipelineService.interceptAdd(PipelinedShapeModification) line: 79	
CommonViewer.add(Object, Object[]) line: 260	
CommonViewer(AbstractTreeViewer).add(Object, Object) line: 593	
PackageExplorerContentProvider$4.run() line: 629	
PackageExplorerContentProvider$7.run() line: 666	

------------------------------------
trace 3: JavaNavigatorContentProvider is called again as a result of the add posted by the resource content provider:
------------------------------------
JavaNavigatorContentProvider.interceptAdd(PipelinedShapeModification) line: 146	
SafeDelegateTreeContentProvider.interceptAdd(PipelinedShapeModification) line: 224	
NavigatorPipelineService.pipelineInterceptAdd(PipelinedShapeModification, ContributorTrackingSet, INavigatorContentDescriptor) line: 95	
NavigatorPipelineService.interceptAdd(PipelinedShapeModification) line: 79	
CommonViewer.add(Object, Object[]) line: 260	
ResourceExtensionContentProvider$2.run() line: 256	
ResourceExtensionContentProvider.runUpdates(Collection) line: 295	
ResourceExtensionContentProvider.access$1(ResourceExtensionContentProvider, Collection) line: 292	
ResourceExtensionContentProvider$1.run() line: 118
Comment 12 Martin Aeschlimann CLA 2007-01-08 05:28:04 EST
not for 3.2.2
Comment 13 Andrew Ferguson CLA 2007-02-11 13:55:38 EST
I've just noticed that in the Project Explorer when running with CDT you get duplicate entries for CDT Projects.

The CDT Navigator Content Provider adds its own ICProject objects in place of the platforms IProject objects, but the IProject objects still appear.

Stepping through whats going on in the debugger, the sequence is
(1) the resources plugin adds its content
(2) the two overriding extensions (CDT, JDT) are processed in that respective order
(3) CDT adds ICProject objects, and remove their corresponding IProject objects
(4) JDT adds both Java and Non-Java projects

the line where non-Java projects are added is:

=====

public Object[] getChildren(Object parentElement) {
		try {
			if (parentElement instanceof IJavaModel) 
				return concatenate(getJavaProjects((IJavaModel)parentElement), getNonJavaProjects((IJavaModel)parentElement));

=====

in

=====
Thread [main] (Suspended)	
	JavaNavigatorContentProvider(PackageExplorerContentProvider).getChildren(Object) line: 202	
	JavaNavigatorContentProvider(StandardJavaElementContentProvider).getElements(Object) line: 151	
	JavaNavigatorContentProvider.getElements(Object) line: 102	
	JavaNavigatorContentProvider.getPipelinedElements(Object, Set) line: 131	
	NavigatorContentServiceContentProvider.pipelineElements(Object, NavigatorContentExtension[], ContributorTrackingSet) line: 355	
	NavigatorContentServiceContentProvider.getElements(Object) line: 162	
	CommonViewer(StructuredViewer).getRawChildren(Object) line: 936	
=====

I'm new to the CNF framework, but reading through this bugzilla - it does sound like the Java content provider should not return content it does not own, and this is consistent with the problem I'm seeing?

thanks,
Andrew
Comment 14 Michael D. Elder CLA 2007-04-25 09:14:26 EDT
This was fixed with the patch for bug 150404.