Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 346002 - Import of User Library with invalid path hoses User Library Dialog -- can not fix
Summary: Import of User Library with invalid path hoses User Library Dialog -- can not...
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.7   Edit
Hardware: Macintosh Mac OS X - Carbon (unsup.)
: P3 major (vote)
Target Milestone: 3.7 RC2   Edit
Assignee: Jay Arthanareeswaran CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-05-16 17:09 EDT by Nathaniel Mills CLA
Modified: 2011-05-23 00:28 EDT (History)
5 users (show)

See Also:
satyam.kandula: review+
markus.kell.r: review+


Attachments
Propsed fix (9.68 KB, patch)
2011-05-18 05:32 EDT, Jay Arthanareeswaran CLA
no flags Details | Diff
Updated patch (10.82 KB, patch)
2011-05-18 11:09 EDT, Jay Arthanareeswaran CLA
no flags Details | Diff
Same patch with updated copyrights (12.06 KB, patch)
2011-05-18 15:21 EDT, Olivier Thomann CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Nathaniel Mills CLA 2011-05-16 17:09:07 EDT
Build Identifier: M20110218-0911

A user library produced on a Windows machine, using external Jar file paths with C:\directory\file.jar was imported without first being fixed into an Eclipse on a MAC.  This causes the contructor for UserLibraryManager to fail in init when the UserLibrary attempts to createFromString (line 188) because the JavaCore.newLibraryEntry method on line 4095 throws an AssertionFaildException Path for IClasspathEntry must be absolute: C:/directory/file.jar.  I tried creating a plugin to allow me to call removeUserLibrary(strULName) but because I can't get the UserLibraryManager to construct the object I can't remove it from the list.  The UserLibrary dialog is hosed due to this error (e.g., you can't see even the working entries, just the error information).

I would recommend a few possible fixes.
a) don't import entries that cause the exception attempting to reference the UserLibrary (perhaps show a dialog for the entries not being imported so the user knows a problem occurred)
b) catch the exception thrown when initializing the User Library dialog and either show the errant entries in the UserLibraries dialog the way they are when the reference a valid path to a non-existant file so at least they could be edited or deleted, or show the error with a Remove invalid entry? OK/Cancel so the dialog can display the valid entries and the invalid ones are gone to be added manually with correct content by the user.

It appears there is an encoding in the user library file (e.g., "WINDOWS-1252") -- if going to Linux or MAC OS, perhaps at least any leading X: could be removed during import so the exception isn't thrown and just a bad entry is displayed and able to be edited?



Reproducible: Always

Steps to Reproduce:
1.Create a userlibrary export file referencing a Windows OS style path:
<?xml version="1.0" encoding="WINDOWS-1252" standalone="no"?>
<eclipse-userlibraries version="2">
    <library name="MyLibTest" systemlibrary="false">
        <archive path="C:/SQLLIB/java/sqlj.zip"/>
        <archive path="C:/SQLLIB/java/Common.jar"/>
    </library>
</eclipse-userlibraries>
2. On a MAC, import this file into the Window / Preferences / Java / Build Path / User Libraries dialog.
3.Try to reopen the User Library dialog -- you will get the error and not be able to remove the MyLibTest user library from the system.  Nor can you add other user libraries.
Comment 1 Olivier Thomann CLA 2011-05-16 20:14:00 EDT
Jay, please follow up.
Comment 2 Jay Arthanareeswaran CLA 2011-05-17 02:28:26 EDT
Reproduced with I20110424-0800.

Markus, do you think it's possible to address this while importing itself? If we want to handle it from the Core, then we might have to be content with an error log rather than display the error to the user.
Comment 3 Jay Arthanareeswaran CLA 2011-05-17 02:32:29 EDT
(In reply to comment #2)
> Reproduced with I20110424-0800.
> 
> Markus, do you think it's possible to address this while importing itself? If
> we want to handle it from the Core, then we might have to be content with an
> error log rather than display the error to the user.

Having said that, I still think it's better if Core handles the exception to cover the scenarios where the exported file might have been altered outside eclipse.

Nathaniel,
Talking about the encoding, the way it works is: if the location selected for export is inside the workspace, the encoding is taken from the workspace or the project settings. Otherwise, UTF-8 is considered as the default encoding.
Comment 4 Olivier Thomann CLA 2011-05-17 08:40:59 EDT
Jay, please prepare a patch. Depending on the risk assessment, it might qualify for RC2.
Comment 5 Markus Keller CLA 2011-05-17 11:07:13 EDT
I agree this should be fixed for RC2.

I quickly investigated why the Windows-style Path "C:/SQLLIB/java/sqlj.zip" came into the system at all. Looks like it's because UserLibraryPreferencePage$LoadSaveDialog.loadLibraries(File) line: 704
now uses "Path.fromPortableString(..)" (to fix bug 78309 and bug 96222).

I guess JDT Core should use a similar approach. Path.fromPortableString(..) resolves a "C:/..."=like path to an absolute path, so if everything works well afterwards, the AFE should not be thrown any more. It would be good to keep the import working even if one of the paths doesn't resolve to a file on disk. This way, it's much easier for the user to correct the situation after the import.

Note that you also have to increase the version number and keep migration code for the old path format. 


Nathaniel: To fix the situation in an older build, please quit Eclipse and then manually edit ".metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.core.prefs" and remove the offending
"org.eclipse.jdt.core.userLibrary.MyLibTest=..." entry.
Comment 6 Jay Arthanareeswaran CLA 2011-05-17 11:42:50 EDT
I am working on a fix for RC2.
Comment 7 Jay Arthanareeswaran CLA 2011-05-18 05:32:49 EDT
Created attachment 195942 [details]
Propsed fix

There are two parts to this fix:

1. As suggested by Markus, to use portable path for user libraries with backward compatibility.
2. Handle exception to cover other scenarios where the path might be invalid. Here I considered two alternatives in case of an exception: 
  i) Remove the preference from the storage for the corrupt library and continue
  ii) Preserve the preference in the storage but do not consider the corresponding user library.

I have decided go with the first, just as has been done in the case of an IOException with the existing code.

The tests are passing on Mac and Windows XP and currently being run on Linux. I will update after the tests complete.
Comment 8 Satyam Kandula CLA 2011-05-18 07:51:45 EDT
The changes are good in general. Minor comments. 
1. The test throws an exception while setting an invalid entry through preferences. As of now, this exception is not being handled through the patch and I think this is fine, as this invalid entry couldn't be given through the UI. 
2. Personally, I feel the following code in UserLibrary.java could be better laid
#######
IPath entryPath = version.equals(VERSION_ONE) ? Path.fromOSString(pathString) : Path.fromPortableString(pathString);

IPath sourceAttachPath = null;
IPath sourceAttachRootPath = null;
if (sourceAttachString != null)
    sourceAttachPath = version.equals(VERSION_ONE) ? Path.fromOSString(sourceAttachString) : Path.fromPortableString(sourceAttachString);
if (sourceAttachRootString != null)
    sourceAttachRootPath = version.equals(VERSION_ONE) ? Path.fromOSString(sourceAttachRootString) : Path.fromPortableString(sourceAttachRootString);
########
as 
#######
if (entryPath.equals(VERSION_ONE)) {
    entryPath = ... // from path
    if (sourceAttachString != null) sourceAttachPath = ...
    if (sourceAttachRootString != null) sourceAttachRootPath = ...
} else { // use portable strings
    entryPath = ... // from portable 
    ....
}
########
Comment 9 Nathaniel Mills CLA 2011-05-18 09:00:37 EDT
Thank you all very much -- I appreciate the work around proposed by Marcus.  I don't know why grep wasn't finding this org.eclipse.jdt.core.prefs file (perhaps ignoring the . prefixed files as though they were hidden (I was searching on Windows with a cygwin based grep).  The fix worked perfectly.
Comment 10 Markus Keller CLA 2011-05-18 09:39:10 EDT
Looks good and works fine, though I agree with Satyam that a single version test would be nicer to read.

Cosmetics: Missing space in "catch(ClasspathEntry.AssertionFailedException e)"
Comment 11 Markus Keller CLA 2011-05-18 09:43:24 EDT
Unfortunately, you don't get an error flag right after importing, see bug 232815. But you get it when you visit the preference page the next time or when you try to build a project with a bad user lib on the build path.
Comment 12 Jay Arthanareeswaran CLA 2011-05-18 11:09:27 EDT
Created attachment 195987 [details]
Updated patch

Patch incorporates comments from Satyam and Markus.
Will release it after running few more tests.
Comment 13 Olivier Thomann CLA 2011-05-18 15:16:58 EDT
Makes sure all copyrights are accurate. This is not the case in this last patch.
Comment 14 Olivier Thomann CLA 2011-05-18 15:21:56 EDT
Created attachment 196039 [details]
Same patch with updated copyrights
Comment 15 Jay Arthanareeswaran CLA 2011-05-19 01:17:06 EDT
Thanks for the patch, Olivier.
Released in HEAD for 3.7 RC2. Tests pass in Linux and Mac too.
Comment 16 Markus Keller CLA 2011-05-20 05:12:37 EDT
Verified in I20110519-1138 on the Mac.
Comment 17 Jay Arthanareeswaran CLA 2011-05-23 00:28:04 EDT
verified by Markus. Marking 'VERIFIED'.