| Summary: | Importing binary project sets a series of default value to absolute paths | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| Product: | [Eclipse Project] JDT | Reporter: | Tod Creasey <Tod_Creasey> | ||||||||
| Component: | Debug | Assignee: | JDT-Debug-Inbox <jdt-debug-inbox> | ||||||||
| Status: | CLOSED WONTFIX | QA Contact: | |||||||||
| Severity: | major | ||||||||||
| Priority: | P2 | CC: | airvine, erich_gamma, jared_burns, Kevin_McGuire, n.a.edgar | ||||||||
| Version: | 2.1 | ||||||||||
| Target Milestone: | --- | ||||||||||
| Hardware: | PC | ||||||||||
| OS: | Windows XP | ||||||||||
| Whiteboard: | |||||||||||
| Bug Depends on: | 33279 | ||||||||||
| Bug Blocks: | 37289 | ||||||||||
| Attachments: |
|
||||||||||
Moving to JDT for comment. Tod, I don't exactly understand the problem. The preference store doesn't contain a JRE_LIB entry. It contains the JRE_CONTAINER. The paths used in the JRE_CONTAINER must be absolute because a JRE_CONTAINER references external Jars that can live outside the workspace. The issue is that it sets a lot of absolute paths without the user ever knowing that they had done so. As a result if you export those preferences and load them back in later you set a lot of values that you didn't intend to - in my case my JRE_LIB ended up pointing to a (deleted) directory from an old build where I had first exported my preference from. If the user adds a JRE using the preference window then he explicitly selects an absolute path in the directory dialog. In your case the VM was automatically detected as the VM used to execute Eclipse. No UI was involved in that. Moving to Debug if they wan't to do anything regarding auto detection and absolute paths. I opt to keep the current implementation though. I didn't set it using a preference window - if you read my steps you will see all I did was run the PDE import wizard and then open the preference window and exported. I agree with you had I set a JRE value but I didn't, I was using auto detect. Leaving it as it is renders preference export useless for anyone who want to also use the PDE. The preferences export JRE home locations - its a fact. This allows the user to set up many JREs and maintain the settings via user preferences (which works great if the JREs are all external to the workspace). The case here is the default detected JRE is within the eclipse install directory, which I assume was removed/deleted. We may be able to special case this, but its low priority. I'm not convinced that this is your issue at all - it only occurs as a knock on effect of using the PDE import wizard. However as far as priority goes it renders export useless in the preference pages. The original complaint seemed to be two-fold. First, that importing your exported preferences "slams" your old preferences. This is the correct behavior for importing exported preferences. Second, that the VM install locations are exported using absolute paths. This "renders export useless". Can you explain exactly how this affect preference export/import? Does it cause some exception to occur that makes the mechanism completely blow up? Otherwise, how does this bug make exporting preferences useless? Based on the discussion since the original report, I interpret your complaint as the following: 1. Launch Eclipse on a VM installed within the Eclipse host installation. 2. Export preferences. The VM paths are stored as absolute paths. 3. Import the exported preferences. 4. The import fails (an exception occurs?) and no preferences are imported, rendering the export/import mechanism useless. Is this correct? No. The issue is that some preferences are set without my knowledge. If I export them and then import them later then values will be set that I am unaware of. It is the fact that these are absolute paths that makes this even worse. I have no complaint about importing preferences changing the ones I already have - that is the point of exporting them... The problem is that the imported preferences point to a JRE in an eclipse install that no longer exists. Only one JRE existed in the workspace - the default, detected JRE - and it was replaced with a preference from the old workspace, which no longer exists. I see. One way to solve this would be to better merge the installed VMs when importing. Based on the problem description, I gather that we competely toss the existing VM installs? Even if there's no conflict with the ones we're importing? I normally run with defaults so in my case it is that the preference gets set rather than being left alone. Are you talking about the fact that we auto-detect a VM? Right - that is the default behaviour and I would want to continue to use that unless I specified otherwise. When you launch your new install of Eclipse in a fresh workspace on a new VM, we will autodetect that VM. I believe you're getting bonked when you import your old preferences because we delete that detected VM and replace it with the imported VM(s). I think the best way to solve this problem is to merge imported VMs into the preferences instead of completely replacing the existing VMs. If an imported VM's location doesn't match an existing VM's location, we should just add it. If the location conflicts, the imported VM install should overwrite the existing one. Any name conflicts can be solved by appending _N to the end of the imported VM's name. We need to be able to tell the difference between a preference import and a user's explicit preference change (they both result in a property change event). However, on the import, I believe we should: (1) If an imported VM's location does not exist, do not add it. (2) Add new VMs (i.e. new existing locations). Rename if there are naming conflicts. (3) If the location is the same as an existing VM - rename the existing VM to the name in the import. However, we need to be able to reliably determine the difference between an import and a user's "save preferences" action. This is a serious issue. Please consider for 2.1. It is highly likely that users of eclipse-based products will encounter this problem. For example: - WSAD 5.0 (based on Eclipse 2.0) install has built-in JRE (autodetected) - user wants to upgrade to WSAD 5.1 so she exports her prefs - installs WSAD 5.1 in new location - uninstalls WSAD 5.0 - imports prefs - tries to build - gets 1000s of errors due to missing VM - compiler error messages don't help in figuring this out. They mention a possible problem in the classpath, but the class path entry for the JRE just says something like "JRE System Library", and gives no indication that its location is invalid Also, so far the discussion has centered on the classpath container entries. The classpath variables added by PDE also use absolute paths back into the plugins dir of the host. Is there any way these could be made relative? Hooking listeners to adapt to preference changes is problematic for two reasons: 1. you can't distinguish between a user change and an import 2. your plugin may not even be active when the prefs are imported It would be better to avoid putting absolute paths in the prefs in the first place. If there was a predefined variable identifying the host's install dir, then could the PDE variables and the default JRE install be in terms of that? This would mean defining variables in terms of other variables, which I guess we don't support. NOTES: * JREs inherently rely on absolute paths (there is nothing that requires a JRE to be in the workspace) * There is a quick fix for when the default/only JRE goes missing * There is a quick fix for when a JRE refereced by a project build path goes missing Another note: the number of errors generated in 2.1 is now small - I believe there are now only 2 errors reported when a JRE goes missing (per project). When you import the preferences does the platform just take the metadata (the strings) from the old preferences and stuff it into the new preferences? Or is there some kind of callback that would allow us to process the incoming data before it's written to the store? If we have an opportunity to process the data when it's imported, doing the merging/validation should be easy. I guess the problem here would be that the platform would have to force all plug-ins with incoming changes to load? If there's no such callback I haven't thought of anything we can do when our plugin isn't loaded. However, when it is loaded can't we distinguish between imports and user saves if we really want to? Example hack: The Installed JREs preference page could set a static "changedByUser" flag true when it saves preference changes. Our preference change listener could check the flag and act accordingly (merging the changes in with the old state in the case where changedByUser is false) and then set the flag to false. There are a number of workarounds here: 1. Install the new version in the same location as the old. 2. Don't delete the old install until you've updated your Installed JREs. 3. Fix the Installed JREs after the fact (see Darin's quick fix notes). Answer to a couple of issues: 1) There is a callabck mechanism on PreferenceStores that will get fired on import (it also gets fired when you change via a preference page as well) called IPropertyChangeListener that you register with the property store that you are interested in - it is already in use by several components. 2) The issue is more reporting of the problem to users as they will have no idea that these changes have been made if they were done under the covers by Eclipse - we at least need a better indication of the problem. 1000+ errors generated by this does not make it clear what the problem is. Adding Kevin McGuire to the list as this also occurs when checking out from a repository. Tod, can you explain how a repository gets involved in your scenario? I thought the problem was caused by importing invalid preferences? Importing from the repository is another way to set preferences without knowing it. So I had a look again during my RC1 testing. STEPS 1) load platform-ui from HEAD 2) add the preqs using binary project import 3) Export preferences 4) Rename the directory of the root install of Eclipse 5) Start another workbench 6) Import preferences I get 12 errors. I it not too hard to see that the rt.jar missing is the issue in this case however the fact that it is JRE lib might take some looking around to figure out (the error should perhaps mention that it is a classpath variable) Checking my preferences Installed JREs is OK Classpath variables is where the problem is If I restore defaults on the classpath variables 1) JRE_LIB shows up as reserved 2) Hit OK 3) Reopen the dialog - it is now shown as the old (imported) value and it is not editable by the user. I think if we at least make it that resetting JRE_LIB really resets to the default then the other issues in the PR are less serious. Logged Bug 33279 to address the JRE_LIB reset issue. We need to further understand this problem. It may be possible to store a preference indicating which VM was the detected VM. When preferences are imported, we should not "import" the detected VM, but rather re-detect. As Nick pointed out, our plug-in has to be loaded for us to register for the property changed callback. Any solution that relies on this callback will not work when the user launches a new install of an Eclipse-based product (like WSAD) for the first time and imports their preferences. Instead, I think we should further investigate why we aren't properly validating the default VM install when the compiler asks us to expand the JRE_CONTAINER variable. Our code clearly intends to handle the case where the default VM is missing and redetect if necessary. If it's missing a case, we should just fix that bug. I investigated this scenario a bit earlier today but when I debugged through our code, we correctly noticed that the VM specified in the preferences was invalid and redetected based on the Eclipse runtime VM. This would seem to indicate that there's a timing problem here but I'm more inclined to believe that I was screwing up my test case. I'll look into this again tomorrow. Perhaps we are just not re-initializing the JRE_LIB variable, as we should when the default VM changes? (see bug 33279) According to my understanding of the problem, the following steps should cause compile errors to show up: 1. Launch Eclipse on a VM in location X. 2. Create a Java project with a HelloWorld class. 3. Export preferences. 4. Close the workbench, rename location X, and relaunch Eclipse on a VM Y. 5. Import preferences. 6. Rebuild All. After step 5 or 6, I'd expect to get errors saying that location X cannot be found, but that's not what happens. Instead, Eclipse is happily noticing that location X is gone and switching to using location Y. What am I missing here? You are missing doing something that will slam the preferences with the hard coded values. 1b) Import a binary project or load a project from a respository. If I replace my step 2 with your 1b, I still don't get any problems. Follow the steps I provided initially. If you follow them you will see the problem in the Java classpath page. Tod, in the steps you first provide, you don't mention when you move the detected JRE that we export and (more importantly) you don't mention the setup of the "different workbench" in step 5. I've tried importing SWT, exporting the preferences, moving the JRE, and importing the preferences with no luck. I've also tried importing the preferences into a new workspace after importing SWT and that doesn't fail either. In your steps from comment #26 confuse me because RC1 doesn't include a JRE in the host install location. Do you just mean move the detected JRE that's been exported? If so, I've tried these steps and I don't get any problems. Can you possibly provide more explicit (hold my hand) instructions for reproducing this problem? Created attachment 3796 [details]
Exported perspectives
These are the perspectives that I exported after loading org.eclipse.swt as a
binary project
Here is the easiesr way to replicate. 1) Start a fresh Eclipse 2) Import the attached preferences 3) Open the Preferences dialog 4) Select Java->classpath variables 5) You will see a bunch of paths set to d:\R21 etc... 6) Reset to defaults. It will look like the defaults with JRE_LIB shown as <reserved> 7) Hit OK 8) Open the preferences dialog. The JRE_LIB will have a path specified that is based on the imported paths. Moving the JRE is not sufficient. You need to start up on a new Eclipse and have the directories in these exported preferences not exist. Following your steps on WinXP and Linux doesn't cause the problem you describe. When we bring the preferences up after restoring defaults, the variables are set to values based on the location of the VM in the Installed JREs preference page (the detected VM we launched on). Is it possible that the problem has something to do with your preferences pointing to invalid locations on our machines? Can you provide steps to reproduce this bug on our own? Steps including the generation of the bad preferences? This is exactly the problem - the locations need to be invalid for me to see this. The steps provided are the ones I used - please give me a call when you get time so that we can figure out what is being done differently. (Steps or no steps) A problem will exist if the install includes a JRE, and a user moves to a new install - the imported preferences will point to the JRE in the old install. WSAD ships with a JRE in the install directory - thus there will be a problem. Suggested fix is to mark the "detected VM" in the exported preferences. Then, when preferences are imported/changed, we do not "add" the VM, we re-detect the VM. After discussing this problem with Erich, we believe that the current behavior is correct. The JRE detection performed when a new (empty) workspace is created is intended to simply help users with the "out-of-the-box" experience. That is, they do not have to define a JRE to get things going - one will be detected for them. Once a workspace has been created, and build paths have been set up to reference that JRE, we no longer wish to automatically change that JRE on the user, as this will also effectively change build paths. We cannot infer when the user wants to change the JRE they are building projects with. For example, if I start Eclipse with a 1.3.1 JRE, create and build some projects, and later re-start my workspace with a 1.4.1 JRE, it should not effect the projects that I have built in my workspace (the Eclipse runtime should not change my buildpath). Development time and IDE runtime should not be tied. Only the user knows when they want to change buildtime (development) time JREs. When a JRE goes missing (and it is referenced on the buildpath), the number of errors reported is small (one or two per project). As well, there is a quickfix to help the user correct the problem. Importing preferences is the same as workspace re-start (we persist the JREs in the workspace, as a prefrence). Thus, if I import preferences which point to invalid JREs, the user will be warned just as if they re-started the workspace and a JRE went missing. There will be a quickfix to help them fix the problem. We do have a bug in our preference update code in that we import non-existant JREs (bug 33893). Assuming that bug is fixed, and there was only ever one JRE in the workspace (as stated in the use case), a default JRE will be re-detected and bound to JRE_LIB. NOTES: (1) we cannot tell the difference between a preference import and a workspace re-start, as there are not explicit notifications that the user is performing an import. As well, our plug-in may not even be active at the time the import is performed. (2) If we did not save the default detected JRE explicitly, then each time the workspace was restarted, the runtime JRE would have to be detected. This means that if the Eclipse runtime changes, the build paths would also change to reflect this, which is undesirable. With Eclipse I200303272130 (RC4) I imported all the plug-ins I required. Then I imported by preferences, previously created by exporting preferences. Now I can not launch a debug session, missing the rt.jar. If I remove the preferences with absolute paths I can then launch eclipse. I believe many users will experience this problem. I did not set these preferences, so they really should not be in my preference file when I export. I have attached two preference files. One has the hardcoded values, the other does not. Again with hard coded values I can not launch a debug session. Withoug hard coded values I can. Created attachment 4385 [details]
Preferences with hardcoded paths
Created attachment 4386 [details]
Preferences without hardcoded paths
Nothing more planned for 3.0 Closing. As of now 'LATER' and 'REMIND' resolutions are no longer supported. Please reopen this bug if it is still valid for you. |
If you import a binary project several values in the preference stores are set to values with absolute paths. If the user later exports thier preferences for use when upgrading a workbench the JRE_LIB will end up pointing to a bogus reference point. STEPS 1) Start a fresh workbench 2) Import swt as a binary project 3) Open the preferences dialog 4) Export preferences 5) If you start a different workbench and import these in this will slam all of your jre locations. Here are the exported preferences - I didn't change anything so these should all still be at thier default values. org.eclipse.jdt.core/org.eclipse.jdt.core.classpathVariable.ORG_ECLIPSE_PLATFOR M_WIN32_SOURCE_SRC=D\:/R21/0211/eclipse/plugins/org.eclipse.platform.win32.sour ce_2.1.0/src org.eclipse.jdt.core=2.1.0 org.eclipse.jdt.launching/org.eclipse.jdt.launching.PREF_VM_XML=<?xml version\="1.0" encoding\="UTF-8"?>\r\n<vmSettings defaultVM\="57,org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType1,0">\r \n <vmType id\="org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType">\r\n <vm id\="0" javadocURL\="http\://java.sun.com/j2se/1.3/docs/api"\r\n name\="eclipse" path\="D\:\\R21\\0211\\eclipse"/>\r\n </vmType>\r\n</vmSettings>\r\n org.eclipse.jdt.core/org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=* .launch org.eclipse.jdt.core/org.eclipse.jdt.core.classpathVariable.ORG_ECLIPSE_PDE_SOU RCE_SRC=D\:/R21/0211/eclipse/plugins/org.eclipse.pde.source_2.1.0/src org.eclipse.jdt.core/org.eclipse.jdt.core.classpathVariable.ORG_ECLIPSE_JDT_SOU RCE_SRC=D\:/R21/0211/eclipse/plugins/org.eclipse.jdt.source_2.1.0/src org.eclipse.jdt.core/org.eclipse.jdt.core.classpathVariable.ECLIPSE_HOME=D\:/R2 1/0211/eclipse org.eclipse.jdt.core/org.eclipse.jdt.core.classpathContainer.org.eclipse.swt|or g.eclipse.jdt.launching.JRE_CONTAINER=<?xml version\="1.0" encoding\="UTF-8"? >\n<classpath><classpathentry kind\="lib" path\="D\:/R21/0211/eclipse/jre/lib/rt.jar" rootpath\="" sourcepath\=""/><classpathentry kind\="lib" path\="D\:/R21/0211/eclipse/jre/lib/i18n.jar" rootpath\="" sourcepath\=""/><classpathentry kind\="lib" path\="D\:/R21/0211/eclipse/jre/lib/ext/ibmjcaprovider.jar" rootpath\="" sourcepath\=""/><classpathentry kind\="lib" path\="D\:/R21/0211/eclipse/jre/lib/ext/indicim.jar" rootpath\="" sourcepath\=""/><classpathentry kind\="lib" path\="D\:/R21/0211/eclipse/jre/lib/ext/JawBridge.jar" rootpath\="" sourcepath\=""/></classpath> org.eclipse.pde.core=2.1.0 org.eclipse.pde.core/platform_path=D\:\\R21\\0211\\eclipse org.eclipse.ui.workbench=2.1.0 org.eclipse.ui.workbench/WELCOME_DIALOG=false org.eclipse.jdt.launching=2.1.0 org.eclipse.jdt.core/org.eclipse.jdt.core.classpathVariable.ORG_ECLIPSE_PLATFOR M_SOURCE_SRC=D\:/R21/0211/eclipse/plugins/org.eclipse.platform.source_2.1.0/src