Bug 16140 - Non-java project gets .classpath
Summary: Non-java project gets .classpath
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 2.0   Edit
Hardware: PC Windows 2000
: P2 normal (vote)
Target Milestone: 2.0 F4   Edit
Assignee: Jerome Lanneluc CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2002-05-16 09:38 EDT by Nick Edgar CLA
Modified: 2002-06-20 11:25 EDT (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Nick Edgar CLA 2002-05-16 09:38:50 EDT
Build 20020515

- I had a binary project in my workspace, which was not a Java project
(org.eclipse.platform.win32)
- replaced it with source from repository
- it's still not a Java project, according to the .project file and the 
project icon (no J decoration)
- however, it got a .classpath file added

Its .project file contains:
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
	<name>org.eclipse.platform.win32</name>
	<comment></comment>
	<projects>
	</projects>
	<buildSpec>
	</buildSpec>
	<natures>
		<nature>org.eclipse.team.cvs.core.cvsnature</nature>
	</natures>
</projectDescription>

May be related to bug 16138
Comment 1 Nick Edgar CLA 2002-05-16 09:40:53 EDT
This is fairly annoying as it dirties the project when I haven't actually made 
any changes.  If I try to delete the file it reappears immediately.

If I delete the binary project first (including contents), then reload from 
source, the problem does not occur.
Comment 2 Erich Gamma CLA 2002-06-05 02:06:14 EDT
moving to JDT Core for investigation.
could be related to 19058
Comment 3 Philipe Mulet CLA 2002-06-05 05:04:58 EDT
Actually, this would rather be a duplicate of bug 18698
Comment 4 Jerome Lanneluc CLA 2002-06-05 06:16:43 EDT
Nick, I don't see source for org.eclipse.platform.win32 in dev.eclipse.org 
(this project contains no .java file). What are your exact steps?
Comment 5 Nick Edgar CLA 2002-06-05 14:37:57 EDT
Correct.  It has no .java files because it's not a Java project.  However, it 
still gets a .classpath when loaded from the repository.
Still occurs on F2.  The steps are:
- import org.eclipse.platform.win32 as a binary project (using PDE importer)
- switch to Navigator view to see it
- load org.eclipse.platform.win32 from dev.eclipse.org using CVS repositories 
view
- notice that it now has a .classpath file
- notice that the .project file does not include the Java nature.

Philippe says this is a dup of bug 18698, which has apparently been fixed since 
F2.
Comment 6 Jerome Lanneluc CLA 2002-06-06 05:14:52 EDT
This is not a dup of bug 18698 as I can reproduce in our latest.

Note that when the project was imported using PDE import, it was given the java 
nature and a .classpath file was created. When the project is imported from the 
repository, it looses its java nature BUT the .classpath is not removed.
Comment 7 Jerome Lanneluc CLA 2002-06-06 05:28:29 EDT
Simpler test case:
1. Create Java project
Observe: a .classpath is created
2. Edit .project file and remove the java builder and java nature
Observe: the .classpath is still present.
Comment 8 Jerome Lanneluc CLA 2002-06-06 05:29:09 EDT
Will consider post 2.0.
Comment 9 Nick Edgar CLA 2002-06-06 08:04:26 EDT
This is a really a PDE problem then.  It shouldn't generate a .classpath if 
it's not a Java project.
Leaving PR here though since you might consider (2) a JDT Core issue.
Not critical for 2.0.
Comment 10 Jerome Lanneluc CLA 2002-06-17 16:46:50 EDT
*** Bug 20485 has been marked as a duplicate of this bug. ***
Comment 11 Jerome Lanneluc CLA 2002-06-18 12:20:26 EDT
Actually, I didn't realize (even if Nick said it :-) that the user could not 
remove the .classpath at all (it is constantly recreated).

Reconsidering for 2.0.
Comment 12 Jerome Lanneluc CLA 2002-06-18 12:22:17 EDT
Simpler test case is:
1. Create simple project
2. Add .classpath file in this project
3. Try to delete the .classpath file
Observe: The .classpath file is recreated right away.
Comment 13 Jerome Lanneluc CLA 2002-06-18 12:25:38 EDT
Problem is with DeltaProcessor.performPreBuildCheck which traverses even non-
java project.

Proposed fix:
	/**
	 * Check whether the updated file is affecting some of the properties 
of a given project (like
	 * its classpath persisted as a file).
	 * Also force classpath problems to be refresh if not running in 
autobuild mode.
	 * NOTE: It can induce resource changes, and cannot be called during 
POST_CHANGE notification.
	 *
	 */
	public void performPreBuildCheck(
		IResourceDelta delta,
		IJavaElement parent) {
	
		IResource resource = delta.getResource();
		IJavaElement element = JavaCore.create(resource);
		boolean processChildren = false;
	
		switch (resource.getType()) {
	
			case IResource.ROOT :
				if (delta.getKind() == IResourceDelta.CHANGED) {
					processChildren = true;
				}
				break;
			case IResource.PROJECT :
				if (delta.getKind() == IResourceDelta.CHANGED 
&& this.hasJavaNature(resource)) {
					processChildren = true;
				}
				break;
			case IResource.FILE :
				if (parent.getElementType() == 
IJavaElement.JAVA_PROJECT) {
					IFile file = (IFile) resource;
					JavaProject project = (JavaProject) 
parent;
	
					/* check classpath property file change 
*/
					QualifiedName classpathProp;
					if (file.getName().equals(
						
	project.computeSharedPropertyFileName(
								classpathProp = 
project.getClasspathPropertyName()))) {
	
						switch (delta.getKind()) {
							case 
IResourceDelta.REMOVED : // recreate one based on in-memory path
								try {
								
	project.saveClasspath(project.getRawClasspath(), 
project.getOutputLocation());
								} catch 
(JavaModelException e) {
									if 
(project.getProject().isAccessible()) {
									
	Util.log(e, "Could not save classpath for "+ project.getPath()); //$NON-
NLS-1$
									}
								}
								break;
							case 
IResourceDelta.CHANGED :
								if 
((delta.getFlags() & IResourceDelta.CONTENT) == 0)
								
	break; // only consider content change
							case 
IResourceDelta.ADDED :
								// check if any 
actual difference
							
	project.flushClasspathProblemMarkers(false, true);
								try {
									// 
force to (re)read the property file
								
	IClasspathEntry[] fileEntries = null;
									try {
									
	String fileClasspathString = project.loadClasspath();
									
	if (fileClasspathString != null) {
										
	fileEntries = project.readPaths(fileClasspathString);
									
	}
									} catch
(JavaModelException e) {
									
	if (project.getProject().isAccessible()) {
										
	Util.log(e, 
										
		"Exception while retrieving "+ project.getPath() //$NON-NLS-1$
										
		+"/.classpath, ignore change"); //$NON-NLS-1$
									
	}
									
	project.createClasspathProblemMarker(
										
	Util.bind("classpath.cannotReadClasspathFile", project.getElementName
()), //$NON-NLS-1$
										
	IMarker.SEVERITY_ERROR,
										
	false,	//  cycle error
										
	true);	//	file format error
									} catch 
(IOException e) {
									
	if (project.getProject().isAccessible()) {
										
	Util.log(e, 
										
		"Exception while retrieving "+ project.getPath() //$NON-NLS-1$
										
		+"/.classpath, ignore change"); //$NON-NLS-1$
									
	}
									
	project.createClasspathProblemMarker(
										
	Util.bind("classpath.cannotReadClasspathFile", project.getElementName
()), //$NON-NLS-1$
										
	IMarker.SEVERITY_ERROR,
										
	false,	//  cycle error
										
	true);	//	file format error
									}
									if 
(fileEntries == null)
									
	break; // could not read, ignore 
									if 
(project.isClasspathEqualsTo(project.getRawClasspath(), 
project.getOutputLocation(), fileEntries))
									
	break;
	
									// will 
force an update of the classpath/output location based on the file information
									// 
extract out the output location
									IPath 
outputLocation = null;
									if 
(fileEntries != null && fileEntries.length > 0) {
									
	IClasspathEntry entry = fileEntries[fileEntries.length - 1];
									
	if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) {
										
	outputLocation = entry.getPath();
										
	IClasspathEntry[] copy = new IClasspathEntry[fileEntries.length - 1];
										
	System.arraycopy(fileEntries, 0, copy, 0, copy.length);
										
	fileEntries = copy;
									
	}
									}
									// 
restore output location				
									if 
(outputLocation == null) {
									
	outputLocation = SetClasspathOperation.ReuseOutputLocation;
									}
								
	project.setRawClasspath(
									
	fileEntries, 
									
	outputLocation, 
									
	null, // monitor
									
	true, // canChangeResource
									
	false, // forceSave
									
	project.getResolvedClasspath(true), // ignoreUnresolvedVariable
									
	true, // needCycleCheck
									
	true); // needValidation
								} catch 
(RuntimeException e) {
									// 
setRawClasspath might fire a delta, and a listener may throw an exception
									if 
(project.getProject().isAccessible()) {
									
	Util.log(e, "Could not set classpath for "+ project.getPath()); //$NON-
NLS-1$
									}
									break;
								} catch 
(CoreException e) {
									// 
happens if the .classpath could not be written to disk
									if 
(project.getProject().isAccessible()) {
									
	Util.log(e, "Could not set classpath for "+ project.getPath()); //$NON-
NLS-1$
									}
									break;
								}
	
						}
					}
				}
				break;
		}
		if (processChildren) {
			IResourceDelta[] children = delta.getAffectedChildren();
			for (int i = 0; i < children.length; i++) {
				performPreBuildCheck(children[i], element);
			}
		}
	}
Comment 14 Jerome Lanneluc CLA 2002-06-18 12:32:16 EDT
Note that with this fix, the .classpath is not deleted when the project looses 
its java nature, but the user CAN now delete it manually.
Comment 15 Nick Edgar CLA 2002-06-18 13:01:52 EDT
Does it also prevent the project from being marked dirty when converted from 
binary to source?
I actually care more about the dirty indication than the free .classpath file.
Comment 16 Jerome Lanneluc CLA 2002-06-18 13:18:40 EDT
I'll assume you convert the project from binary to source by checking out the 
project as you first described. In this case, the .classpath is removed (I 
guess by Team) and it is not being recreated, so the project is not dirty.
Comment 17 Kevin McGuire CLA 2002-06-18 14:18:10 EDT
Correct, when you do a CVS Checkout from the repo browser, all files (but not 
the project itself) are deleted and new ones written.

Preventing the re-generation of the .classpath is goodness.
Comment 18 Philipe Mulet CLA 2002-06-18 17:58:27 EDT
Fix is trivial, simply ignore delta on .classpath file if not belong to project 
with java nature. Consequences are fairly nasty if not fixed, .classpath file 
is recreated instantaneously and causing confusion.

 
Comment 19 Philipe Mulet CLA 2002-06-18 18:24:43 EDT
Should fix for F4
Comment 20 Jerome Lanneluc CLA 2002-06-19 06:17:08 EDT
Indeed the fix is trivial and should be fixed for F4.
Comment 21 David Audel CLA 2002-06-19 09:26:29 EDT
The problem does not exists in 1.0.
Comment 22 Jerome Lanneluc CLA 2002-06-20 05:33:51 EDT
Entered bug 20708 to reflect that JDT/Core still needs to remove the .classpath 
file when a project looses its java nature.
Comment 23 Philipe Mulet CLA 2002-06-20 07:26:41 EDT
Fix got approved, released in 20020620.
Comment 24 David Audel CLA 2002-06-20 11:25:25 EDT
Verified.