Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 326581

Summary: Provide Resource resolution to IJavaProjectProvider
Product: [Modeling] TMF Reporter: Ed Willink <ed>
Component: XtextAssignee: Project Inbox <tmf.xtext-inbox>
Status: CLOSED WORKSFORME QA Contact:
Severity: enhancement    
Priority: P3 CC: oliver.libutzki, sven.efftinge
Version: 1.0.0   
Target Milestone: ---   
Hardware: PC   
OS: Windows Vista   
Whiteboard:

Description Ed Willink CLA 2010-09-29 15:03:51 EDT
If Resource A references Resource B which references Resource C which has JDT type proxies, the correct classpath  for resolution of the proxies from Resource C is provided by the plugin/project in which Resource C resides. The relevant classes need not be present in the classpath of the plugin/project in which Resource A resides.

If IJavaProjectProvider.getJavaProject was passed the referencing Resource rather than its ResourceSet, the appropriate Resource-specific IJavaProject and so classpath can be identified.

This would avoid the following overload of XtextResourceSetBasedProjectProvider for ordinary ResourceSets needing to use the first IJavaProject rather than the correct one.

	public IJavaProject getJavaProject(ResourceSet resourceSet) {
		IJavaProject javaProject = super.getJavaProject(resourceSet);
		if (javaProject == null) {
			for (Resource resource : resourceSet.getResources()) {
				URI uri = resource.getURI();
				if (uri.isPlatformResource()) {
					IWorkspace workspace = ResourcesPlugin.getWorkspace();
	                IProject iProject = workspace.getRoot().getProject(uri.segments()[1]);
	                if (iProject != null) {
		            	javaProject = JavaCore.create(iProject);
		            	break;
	                }
				}
				else if (uri.isPlatformPlugin()) {
		            final Bundle bundle = Platform.getBundle(uri.segment(1));
		            if (bundle != null) {
		            	// FIXME 
		            }
				}
			}
		}
		return javaProject;
	}
Comment 1 Sven Efftinge CLA 2010-09-30 03:09:55 EDT
(In reply to comment #0)
> If Resource A references Resource B which references Resource C which has JDT
> type proxies, the correct classpath  for resolution of the proxies from
> Resource C is provided by the plugin/project in which Resource C resides. The
> relevant classes need not be present in the classpath of the plugin/project in
> which Resource A resides.
> 
> If IJavaProjectProvider.getJavaProject was passed the referencing Resource
> rather than its ResourceSet, the appropriate Resource-specific IJavaProject and
> so classpath can be identified.

This would mimic the runtime osgi behavior, but not the runtime behavior of a vanilla Java process with just one classloader.
If you ran a class from project A, which references a class from project B which references a class from project C which is not on the classpath of project A, you would end up with a NoClassDefFoundError (resp. ClassNotFoundException) as soon as some code tries to access the class from project C. 
So that's OSGi vs. flat classloading.

Anyway, it seems like in the case of IJavaProjectProvider the current clients always have a Resource, which they could pass in. The default implementation still should be based on the ResourceSet of the passed in Resource.
Comment 2 Ed Willink CLA 2010-09-30 04:26:35 EDT
Certainly for a standalone application, the application is responsible, aided by setup routines, for providing a comprehensive classpath for its class loader.

However for an Eclipse/OSGI application, OSGI behaviour is exactly what I am suggesting mimicking. By using the resource-specific IJavaProject, the resource-specific class loader is used avoiding the CNFE. A project may therefore reference third party resources without needing to be aware of the transitive classpaths necessary to successfully use those resources.

I find classpaths incredibly confusing, so maybe I'm completely wrong, but it seems that we can ensure that the Xtext extension of Resources with JDT proxies can work in ordinary modeling projects provided the referencing resource is knowable when locating the IJavaProject.

For standalone applications, knowledge of the referencing resource may enable a better diagnostic to be produced to help the developer get the application right.
Comment 3 Oliver L CLA 2012-01-26 04:30:48 EST
*** Bug 369773 has been marked as a duplicate of this bug. ***
Comment 4 Sven Efftinge CLA 2012-11-20 11:12:15 EST
Binding a single JavaProject to the ResourceSet is reasonable, since the static validation happens in such a context. I.e. you should not resolve links beyond what's on the scope.
We rather want to improve the lazy transient resolution of JvmTypes.