Bug 37111 - classpath file - java source attachment shouldn't hardcode project name
Summary: classpath file - java source attachment shouldn't hardcode project name
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 2.1   Edit
Hardware: PC Windows 2000
: P3 normal (vote)
Target Milestone: 3.0 M1   Edit
Assignee: Philipe Mulet CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2003-04-30 14:38 EDT by JJ CLA
Modified: 2003-06-06 06:47 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 JJ CLA 2003-04-30 14:38:40 EDT
When using the java source attachment the .classpath file should not hardcode
the project name. 

sourcepath="/projectname/ext-dist/log4j-1.2.7.zip"

This is a problem because we check in the .classpath file.  

Now anyone who doesn't name their project "projectname" will not be able to jump
into that source.  

This is not the only issue it also becomes a problem if you have to work on
multiple branchs and can not have two projects with the same name, although the
non projectname named project would end up using the projectname source jar
files this isn't a good thing since they could be different versions or no
longer exist.

The source path should assume the current project.

The only work around seems to be to create another cvs project which contains
only source jars but then even that fails to work if you are working on multiple
versions where those version have changes in the source jar files.
Comment 1 Philipe Mulet CLA 2003-05-12 12:51:13 EDT
You could use variables to abstract this information. Our assumption is that 
project names are stable (thus we support project name references for 
prerequisites). 

No plan to change this.
Comment 2 JJ CLA 2003-05-12 13:28:39 EDT
It is true that I could use a variable to abstract this information but I think
the source library should default fall under the same category as the bytecode
libraries.  For instance to reference a byteclass library the .classpath file
will use an entry like this:  

<classpathentry kind="lib" path="lib/log4j.jar"/>

Note that the project the library is not contained in the path.  Now to include
the source for this library the entry changes to this:


<classpathentry kind="lib" path="lib/log4j.jar"
sourcepath="/projects/src-libs/log4j-1.2.7.zip"/>

Note that now I do have to reference the project name.  

But let's ignore the unconsistant feel of this approach for the moment.

Lets assume I have a product with one branch and the trunk.  I initially create
the product in cvs as "product" so my classpath file has the entry:
sourcepath="/product/src-libs/log4j-1.2.7.zip".   Now we finish that version of
the product and that file is now part of the version1 branch.  

Both the head and the branch now have a .classpath file with
sourcepath="/product/src-libs/log4j-1.2.7.zip".  This works in the case of the
head but now I check out the branch and it is referencing the source library
from the head.  This is a problem for many reasons - src lib could be
updated/deleted/etc.  

Now the question is can using a variable to reference the product really help
me.  It would seem to me that the only way that using a variable would help me
is if everytime after branching I created a new variable maybe VersionX and then
updated every entry in the classpath to use that new variable.  I think that is
too much overhead and complicates the workflow a lot.  




    
Comment 3 Philipe Mulet CLA 2003-05-29 18:12:41 EDT
Actually, I see your original point now. The source attachment should be 
shortened in a project relative form as the library path is already. It should 
only include the project name if located outside of the referring project.

Comment 4 Philipe Mulet CLA 2003-05-29 18:52:39 EDT
Patch on ClasspathEntry:
	/**
	 * Returns the XML encoding of the class path.
	 */
	public Element elementEncode(
		Document document,
		IPath projectPath)
		throws JavaModelException {

		Element element = document.createElement("classpathentry"); //
$NON-NLS-1$
		element.setAttribute("kind", kindToString(this.entryKind));
	//$NON-NLS-1$
		IPath xmlPath = this.path;
		if (this.entryKind != IClasspathEntry.CPE_VARIABLE && 
this.entryKind != IClasspathEntry.CPE_CONTAINER) {
			// translate to project relative from absolute 
			if (xmlPath.isAbsolute()) {
				if (projectPath != null && 
projectPath.isPrefixOf(xmlPath)) {
					if (xmlPath.segment(0).equals
(projectPath.segment(0))) {
						xmlPath = 
xmlPath.removeFirstSegments(1);
						xmlPath = xmlPath.makeRelative
();
					} else {
						xmlPath = xmlPath.makeAbsolute
();
					}
				}
			}
		}
		element.setAttribute("path", xmlPath.toString()); //$NON-NLS-1$

		// translate to project relative from absolute 
		if (this.sourceAttachmentPath != null) {
			xmlPath = this.sourceAttachmentPath;
			if (projectPath != null && projectPath.isPrefixOf
(xmlPath)) {
				if (xmlPath.segment(0).equals
(projectPath.segment(0))) {
					xmlPath = xmlPath.removeFirstSegments
(1);
					xmlPath = xmlPath.makeRelative();
				} else {
					xmlPath = xmlPath.makeAbsolute();
				}
			}
			element.setAttribute("sourcepath", xmlPath.toString
()); //$NON-NLS-1$
		}
		if (this.sourceAttachmentRootPath != null) {
			element.setAttribute("rootpath", 
this.sourceAttachmentRootPath.toString()); //$NON-NLS-1$
		}
		if (this.isExported) {
			element.setAttribute("exported", "true"); //$NON-NLS-1
$ //$NON-NLS-2$
		}
		
		if (this.exclusionPatterns.length > 0) {
			StringBuffer excludeRule = new StringBuffer(10);
			for (int i = 0, max = this.exclusionPatterns.length; i 
< max; i++){
				if (i > 0) excludeRule.append('|');
				excludeRule.append(this.exclusionPatterns[i]);
			}
			element.setAttribute("excluding", excludeRule.toString
());  //$NON-NLS-1$
		}
		
		if (this.specificOutputLocation != null) {
			IPath outputLocation = 
this.specificOutputLocation.removeFirstSegments(1);
			outputLocation = outputLocation.makeRelative();
			element.setAttribute("output", outputLocation.toString
()); //$NON-NLS-1$ 
		}
		return element;
	}
	
	public static IClasspathEntry elementDecode(Element element, 
IJavaProject project) {
	
		IPath projectPath = project.getProject().getFullPath();
		String kindAttr = element.getAttribute("kind"); //$NON-NLS-1$
		String pathAttr = element.getAttribute("path"); //$NON-NLS-1$

		// ensure path is absolute
		IPath path = new Path(pathAttr); 		
		int kind = kindFromString(kindAttr);
		if (kind != IClasspathEntry.CPE_VARIABLE && kind != 
IClasspathEntry.CPE_CONTAINER && !path.isAbsolute()) {
			path = projectPath.append(path);
		}
		// source attachment info (optional)
		IPath sourceAttachmentPath = 
			element.hasAttribute("sourcepath")	//$NON-NLS-1$
			? new Path(element.getAttribute("sourcepath")) //$NON-
NLS-1$
			: null;
		if (sourceAttachmentPath != null && !
sourceAttachmentPath.isAbsolute()) {
			sourceAttachmentPath = projectPath.append(path);
		}
		IPath sourceAttachmentRootPath = 
			element.hasAttribute("rootpath") //$NON-NLS-1$
			? new Path(element.getAttribute("rootpath")) //$NON-NLS-
1$
			: null;
		
		// exported flag (optional)
		boolean isExported = element.getAttribute("exported").equals
("true"); //$NON-NLS-1$ //$NON-NLS-2$

		// exclusion patterns (optional)
		String exclusion = element.getAttribute("excluding"); //$NON-
NLS-1$ 
		IPath[] exclusionPatterns = 
ClasspathEntry.NO_EXCLUSION_PATTERNS;
		if (!exclusion.equals("")) { //$NON-NLS-1$ 
			char[][] patterns = CharOperation.splitOn('|', 
exclusion.toCharArray());
			int patternCount;
			if ((patternCount  = patterns.length) > 0) {
				exclusionPatterns = new IPath[patternCount];
				for (int j = 0; j < patterns.length; j++){
					exclusionPatterns[j] = new Path(new 
String(patterns[j]));
				}
			}
		}

		// custom output location
		IPath outputLocation = element.hasAttribute("output") ? 
projectPath.append(element.getAttribute("output")) : null; //$NON-NLS-1$ //$NON-
NLS-2$
		
		// recreate the CP entry
		switch (kind) {

			case IClasspathEntry.CPE_PROJECT :
				return JavaCore.newProjectEntry(path, 
isExported);
				
			case IClasspathEntry.CPE_LIBRARY :
				return JavaCore.newLibraryEntry(
										
		path,
										
		sourceAttachmentPath,
										
		sourceAttachmentRootPath,
										
		isExported);
				
			case IClasspathEntry.CPE_SOURCE :
				// must be an entry in this project or specify 
another project
				String projSegment = path.segment(0);
				if (projSegment != null && projSegment.equals
(project.getElementName())) { // this project
					return JavaCore.newSourceEntry(path, 
exclusionPatterns, outputLocation);
				} else { // another project
					return JavaCore.newProjectEntry(path, 
isExported);
				}

			case IClasspathEntry.CPE_VARIABLE :
				return JavaCore.newVariableEntry(
						path,
						sourceAttachmentPath,
						sourceAttachmentRootPath, 
						isExported);
				
			case IClasspathEntry.CPE_CONTAINER :
				return JavaCore.newContainerEntry(
						path,
						isExported);

			case ClasspathEntry.K_OUTPUT :
				if (!path.isAbsolute()) return null;
				return new ClasspathEntry(
						ClasspathEntry.K_OUTPUT,
						IClasspathEntry.CPE_LIBRARY,
						path,
					
	ClasspathEntry.NO_EXCLUSION_PATTERNS, 
						null, // source attachment
						null, // source attachment root
						null, // custom output location
						false);
			default :
				throw new Assert.AssertionFailedException
(Util.bind("classpath.unknownKind", kindAttr)); //$NON-NLS-1$
		}
	}
Comment 5 Philipe Mulet CLA 2003-06-02 06:09:25 EDT
Fixed in latest. Source attachments will be project relative when applicable.
Comment 6 David Audel CLA 2003-06-06 06:47:53 EDT
Verified.