Bug 417869 - Plugin launch configuration does not include Bundle-Classpath jar files
Summary: Plugin launch configuration does not include Bundle-Classpath jar files
Status: VERIFIED FIXED
Alias: None
Product: PDE
Classification: Eclipse Project
Component: UI (show other bugs)
Version: 4.3   Edit
Hardware: PC Windows 7
: P3 normal with 2 votes (vote)
Target Milestone: 4.17 M1   Edit
Assignee: Julian Honnen CLA
QA Contact:
URL:
Whiteboard:
Keywords: contributed, helpwanted, investigate
: 564790 (view as bug list)
Depends on: 327371
Blocks: 565105
  Show dependency tree
 
Reported: 2013-09-23 15:29 EDT by Curtis Windatt CLA
Modified: 2020-07-10 04:21 EDT (History)
15 users (show)

See Also:


Attachments
A dev.properties of a eclipse 4.2 project (1.90 KB, text/plain)
2013-10-14 03:03 EDT, Torsten Schöne CLA
no flags Details
The same dev.properties with 4.3 (8.52 KB, text/plain)
2013-10-14 03:04 EDT, Torsten Schöne CLA
no flags Details
Simple test case to replicate the problem (5.07 KB, application/zip)
2016-10-20 05:40 EDT, Michal Kostrzewa CLA
no flags Details
Patch reverting 327371 (2.43 KB, patch)
2016-10-20 16:05 EDT, Michal Kostrzewa CLA
no flags Details | Diff
Patch against oxygen2 which fixes the issue (2.42 KB, patch)
2018-02-23 05:58 EST, Michal Kostrzewa CLA
no flags Details | Diff
sample projects for reproduction (9.48 KB, application/x-zip-compressed)
2019-05-20 09:55 EDT, Julian Honnen CLA
no flags Details
screenshot of the issue (122.03 KB, image/png)
2019-07-04 06:26 EDT, Julian Honnen CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Curtis Windatt CLA 2013-09-23 15:29:23 EDT
Followup to Bug 327371 as it may be causing a regression...

since the switch to 4.3.0 as IDE (!) we have a problem with our application (same target platform as before the switch (Eclipse 3.8.0)): We have a MANIFEST.MF doing this:

Bundle-ClassPath: .,
 lib/slf4j-log4j12-1.6.1.jar,
 lib/mail.jar,
 lib/jul-to-log4j-20090813.jar,
 lib/log4j-component-20090813.jar,
 lib/log4j-extras-20090813.jar,
 lib/slf4j-api-1.6.1.jar

Now, all classpath entries appear TWICE when launching from the IDE. We debugged a little, and discovered that when adding "." to the classpath (in org.eclipse.osgi.baseadaptor.loader.ClasspathManager.findClassPathEntry), the org.eclipse.osgi.internal.baseadaptor.DevClassLoadingHook adds too many classpath entries. it adds not only ".", but finds all the jar files also. After this, the jar files are added /again/ from org.eclipse.osgi.baseadaptor.loader.ClasspathManager.addClassPathEntry (also called from findClassPathEntry).

I think the previous "fix" from this bug is the cause of the problem. In our scenario this means that slf4j gets on the classpath twice, yielding this:

SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [bundleresource://64.fwk175408781:6/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [bundleresource://64.fwk175408781:13/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.

I think there is more to do .... can somebody please reopen?


+++ This bug was initially created as a clone of Bug #327371 +++

Build Identifier: 20100917-0705

I have a plugin that contains some binary jar files. These are correctly added to the Bundle-Classpath and should be part of the plugin when run through the launch configuration. Only the output class file directories are placed on the runtime classpath.

I did some investigation into the PDE code to see where the problem lies. The ClasspathHelper class correctly looks through each library on the Bundle-Classpath to add them to the runtime path. The problem comes in when it looks at the JDT classpath. The 'getClasspathMap' method is used to find the actual jar to resolve the bundle classpath. This method though ignores all jar files (CP_LIBRARY) unless they are linked. This is causing the jars to not be added to dev.properties.

The PDE launcher should respect the classpath defined by the manifest and include jar files even if they are not linked or the bundle ID is 'org.eclipse.osgi'.

---

A sample testcase project is included as an attachment. Details are described below...

Contents of Manifest.MF:

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Test-pde-project
Bundle-SymbolicName: test-pde-project
Bundle-Version: 1.0.0.qualifier
Require-Bundle: org.eclipse.ui,
 org.eclipse.core.runtime
Bundle-ClassPath: plugin-out.jar,
 lib/dummy.jar

Contents of build.properties:

source.plugin-out.jar = src/
output.. = bin/
bin.includes = META-INF/,\
               plugin-out.jar,\
               lib/dummy.jar

plugin-out.jar is the output jar file that should be created from the source of the plugin. The dummy.jar file should also be included in the runtime classpath. Both of these should be in dev.properties when the PDE launches eclipse. This is what is actually generated in dev.properties:

#
#Wed Oct 06 10:11:09 ADT 2010
test-pde-project=bin
@ignoredot@=true

Reproducible: Always

Steps to Reproduce:
1. Load the attached project.
2. Run the 'Eclipse Application' launcher from the configuration file.
3. Check .metadata\.plugins\org.eclipse.pde.core\Eclipse Application\dev.properties to see if it correctly included the jar files from the Bundle-Classpath.
Comment 1 Markus Duft CLA 2013-09-25 01:47:36 EDT
from what i saw, it seems that the dev.properties /should/ contain only the bin directory, to adapt to the development environment layout of the files on disc. the rest of the classpaths is handled as if the plugin where an unpacked jar somewhere on disc, right? that would completely explain the observation of the duplicate classpath :)
Comment 2 Torsten Schöne CLA 2013-10-14 03:03:01 EDT
Created attachment 236442 [details]
A dev.properties of a eclipse 4.2 project
Comment 3 Torsten Schöne CLA 2013-10-14 03:04:26 EDT
Created attachment 236443 [details]
The same dev.properties with 4.3
Comment 4 Michal Kostrzewa CLA 2016-10-20 05:40:31 EDT
Created attachment 264952 [details]
Simple test case to replicate the problem

This is the simple test case I replicated this issue with the newest eclipse 

Version: Neon.1a Release (4.6.1)
Build id: 20161007-1200

The core of this app is these lines

for (Enumeration<URL> urls = Application.class.getClassLoader().getResources("/dummy.properties"); 
					urls.hasMoreElements();)
			{
				URL url = urls.nextElement();
				System.out.println("url = " + url);
			}

(the /dummy.properties is inside a jar)

When launched from the IDE it procduces
url = bundleresource://14.fwk1458540918/dummy.properties
url = bundleresource://14.fwk1458540918:2/dummy.properties

When exported and launched it produces
url = bundleresource://14.fwk1344645519/dummy.properties
Comment 5 Michal Kostrzewa CLA 2016-10-20 16:05:57 EDT
Created attachment 264979 [details]
Patch reverting 327371

The way I understand it is as follows.

The dev.properties file produced by PDE was meant to export classpath entries that are present only in development mode, and not present after exporting (like the bin folder). As such they should NOT export embedded jars, because jars will be added to the classpath anyway based on Bundle-ClassPath manifest attribute. 

When Curtis Windatt CLA @ 2012-06-28 17:34:56 EDT of bug 327371 says

"I don't know why this was a restriction in the first place (it's been this way for 5 years)."

then I think it was meant to be this way and it used to work even with embedded jars. I checked eclipse 3.4.1 which wasn't producing these jar entries in dev.properties and yet all the jars present on Bundle-ClassPath were properly resolved in dev mode. 

In the code see class

org.eclipse.osgi.internal.loader.classpath.ClasspathManager, method findClassPathEntry. What it does is this:

private void findClassPathEntry(ArrayList<ClasspathEntry> result, String cp, ClasspathManager hostloader, Generation sourceGeneration) {
		List<ClassLoaderHook> loaderHooks = hookRegistry.getClassLoaderHooks();
		boolean hookAdded = false;
		for (ClassLoaderHook hook : loaderHooks) {
			hookAdded |= hook.addClassPathEntry(result, cp, hostloader, sourceGeneration);
		}
		if (!addClassPathEntry(result, cp, hostloader, sourceGeneration) && !hookAdded) {
			BundleException be = new BundleException(NLS.bind(Msg.BUNDLE_CLASSPATH_ENTRY_NOT_FOUND_EXCEPTION, cp, sourceGeneration.getRevision().toString()), BundleException.MANIFEST_ERROR);
			sourceGeneration.getBundleInfo().getStorage().getAdaptor().publishContainerEvent(ContainerEvent.INFO, sourceGeneration.getRevision().getRevisions().getModule(), be);
		}
	}

The loaderHooks list in the first part of this method have hook org.eclipse.osgi.internal.hooks.DevClassLoadingHook, which is responsible for adding these dev.properties entries. In current neon 4.6.1 and my testcase it adds both bin and dummy.jar. 

Then in the next part you see a call to addClassPathEntry, which in turns calls addStandardClassPathEntry which always adds dummy.jar again (!).

This usually doesn't hurt when one just loads classes, or calls Class.getResource, but does hurt when Classloader.getResources() because in this case resources returned are always duplicated.

I'm attaching a PDE patch against commit 1470b7c7056bd80c8c283fd937bc0ae07bc453cd which reverses #327371 and which works for me (doesn't duplicate jar entries when launching from PDE) and embedded jars also work.
Comment 6 Michal Kostrzewa CLA 2018-02-23 03:28:24 EST
I replicated this same problem (using my "Simple test case to replicate the problem" test case attached to this ticket) with the newest Eclipse

Version: Oxygen.2 Release (4.7.2)
Build id: 20171218-0600

This problem is a killer one in my case, where I use a 3rd party library which internally calls ClassLoader.getResources(), gets duplicated entries and becomes confused because of this. It only works with the exported product which makes programming difficult to say the least (not until you patch eclipse).
Comment 7 Torsten Schöne CLA 2018-02-23 04:16:30 EST
Hello Michal,

i had the same problem a few years ago and if i remember correctly following change helped:

I added org.eclipse.equinox.simpleconfigurator and org.eclipse.equinox.simpleconfigurator.manipulator to my runconfig with start-level 1 and auto-start true. 
That bundle generates or processes the dev.properties in a different way which works.
Comment 8 Michal Kostrzewa CLA 2018-02-23 05:57:36 EST
Torsten,

thank you for sharing this. How did you find this information?

Just to confirm - you modified config.ini of the eclipse IDE itself and modified osgi.bundles entry, is this correct?

The original oxygen2's config.ini already has some simpleconfigurator related entry, see below

osgi.bundles=reference\:file\:org.eclipse.equinox.simpleconfigurator_1.2.0.v20170110-1705.jar@1\:start
org.eclipse.equinox.simpleconfigurator.configUrl=file\:org.eclipse.equinox.simpleconfigurator/bundles.info

I tried adding manipulator there, but it didn't work, I may well be doing something wrong though.

I'm attaching the patch against org.eclipse.pde.core in oxygen2 that works for me.
Comment 9 Michal Kostrzewa CLA 2018-02-23 05:58:29 EST
Created attachment 272849 [details]
Patch against oxygen2 which fixes the issue
Comment 10 Torsten Schöne CLA 2018-02-26 05:43:02 EST
(In reply to Michal Kostrzewa from comment #8)
> thank you for sharing this. How did you find this information?
I think i saw something in a similar bug report about features and checked the differences.

> Just to confirm - you modified config.ini of the eclipse IDE itself and
> modified osgi.bundles entry, is this correct?
I just added the two bundles in the Plug-Ins tab of my run configurations.
Comment 11 Vikas Chandra CLA 2018-04-18 05:21:20 EDT
Bulk move out of 4.8 target milestone.
Comment 12 Alain Picard CLA 2019-01-08 14:44:30 EST
Why do we have a patch and this is not being addressed?

Alain
Comment 13 Andrey Loskutov CLA 2019-01-09 04:54:05 EST
(In reply to Alain Picard from comment #12)
> Why do we have a patch and this is not being addressed?

Because no one has time to work on this?
You can help if you rebase the patch on master and provide a *Gerrit* patch.

See https://wiki.eclipse.org/Platform_UI/How_to_Contribute
Comment 14 Julian Honnen CLA 2019-01-09 06:17:39 EST
Isn't the test case from comment 4 basically the same as the one from the original bug?

If yes, what did the original bug actually fix? Whether the library is added to dev.properties or not seems like an irrelevant implementation detail as long as it's on the runtime classpath.
Comment 15 Eclipse Genie CLA 2019-05-20 08:42:30 EDT
New Gerrit change created: https://git.eclipse.org/r/142435
Comment 16 Julian Honnen CLA 2019-05-20 09:50:37 EDT
(In reply to Eclipse Genie from comment #15)
> New Gerrit change created: https://git.eclipse.org/r/142435

That's the attached patch, reverting the change from Bug 327371.

So far I haven't seen any regression with it and I still don't see any reason for the initial change. Let's merge this early 4.13.
Comment 17 Julian Honnen CLA 2019-05-20 09:55:09 EDT
Created attachment 278666 [details]
sample projects for reproduction

Without the revert, running the test.product prints the dummy.properties from test-rcp/dummy.jar twice:

class from JAR: class lib.A
class from fragment's JAR: class lib.ClassFromFragment
url = bundleresource://26.fwk329645619/dummy.properties
url = bundleresource://26.fwk329645619:2/dummy.properties

With the revert, it exists only once on the classpath as expected while classes from the jars still load fine:

class from JAR: class lib.A
class from fragment's JAR: class lib.ClassFromFragment
url = bundleresource://26.fwk329645619:1/dummy.properties
Comment 19 Julian Honnen CLA 2019-07-04 06:24:49 EDT
Found the cause for the original bug... Repro:

1) import the plugins from comment 17
2) launch an eclipse SDK from that workspace
3) create a plugin in the launched eclipse with a dependency to library-bundle

The PDE classpath container for that bundle only contains the bin classpath folder, not the lib.jar.


Cause: After the revert, the dev.properties only contain a 'bin' entry. The lib.jar is omitted as it's in the same location during dev-time.

When the launched SDK initializes its PDE state, TargetWeaver *overrides* the full Bundle-ClassPath header with the dev.properties entry, thereby removing the lib.jar.

To summarize there are 3 components to this issue:
1) PDE from the IDE, writing the dev.properties
2) OSGi's ClasspathManager, which loads the the original classpath header and
   *additionally* the dev properties
3) PDE from the target platform (typically in an older version than 1.), which
   loads *only* the dev properties entries
Comment 20 Julian Honnen CLA 2019-07-04 06:26:23 EDT
Created attachment 279175 [details]
screenshot of the issue
Comment 21 Eclipse Genie CLA 2019-07-04 06:38:15 EDT
New Gerrit change created: https://git.eclipse.org/r/145464
Comment 23 Julian Honnen CLA 2019-07-04 08:16:10 EDT
(In reply to Eclipse Genie from comment #22)
> Gerrit change https://git.eclipse.org/r/145464 was merged to [master].
> Commit:
> http://git.eclipse.org/c/pde/eclipse.pde.ui.git/commit/
> ?id=413e629425b5520799c4a992f2335bb99aa64ee4

reverted the revert for M1.

@Vikas, Thomas: Any idea how to handle this interdependence between PDE/OSGi in IDE and target properly?

1) should PDE (from target) treat dev.properties as classpath *additions* like 
   OSGi or should OSGi ensure that DevClassLoadingHook doesn't add duplicate 
   entries?
2) how can we ensure, that a new IDE PDE works with older target PDE versions?
   Should there be some versioning in dev.properties? Can we test that?
Comment 24 Vikas Chandra CLA 2019-08-19 06:29:02 EDT
Moving out of 4.13.
Comment 25 Julian Honnen CLA 2020-07-01 02:50:20 EDT
*** Bug 564790 has been marked as a duplicate of this bug. ***
Comment 26 Thomas Watson CLA 2020-07-01 09:23:46 EDT
(In reply to Julian Honnen from comment #23)
> (In reply to Eclipse Genie from comment #22)
> > Gerrit change https://git.eclipse.org/r/145464 was merged to [master].
> > Commit:
> > http://git.eclipse.org/c/pde/eclipse.pde.ui.git/commit/
> > ?id=413e629425b5520799c4a992f2335bb99aa64ee4
> 
> reverted the revert for M1.
> 
> @Vikas, Thomas: Any idea how to handle this interdependence between PDE/OSGi
> in IDE and target properly?
> 
> 1) should PDE (from target) treat dev.properties as classpath *additions*
> like 
>    OSGi or should OSGi ensure that DevClassLoadingHook doesn't add duplicate 
>    entries?
> 2) how can we ensure, that a new IDE PDE works with older target PDE
> versions?
>    Should there be some versioning in dev.properties? Can we test that?

Sorry I missed this question from a year ago!

Let me first understand the usages of the dev.properties that PDE manages.  Up until now, I only thought that was read by the framework at runtime when in "dev mode".  I did not think that file was used at all to calculate the classpath container for PDE.  Are you suggesting this file that PDE itself manages also contributes to PDE's own classpath container?
Comment 27 Julian Honnen CLA 2020-07-01 09:57:18 EDT
(In reply to Thomas Watson from comment #26)
> Let me first understand the usages of the dev.properties that PDE manages. 
> Up until now, I only thought that was read by the framework at runtime when
> in "dev mode".  I did not think that file was used at all to calculate the
> classpath container for PDE.  Are you suggesting this file that PDE itself
> manages also contributes to PDE's own classpath container?
Yes. Same as the framework, PDE adapts the library entries from the Manifest to the actual locations during dev mode.
That happens in 
org.eclipse.pde.internal.core.MinimalState.addBundle(File, long)

Maybe we could lookup the framework's bundle description for the given location and simply copy that into PDE's state?
Comment 28 Eclipse Genie CLA 2020-07-01 10:36:49 EDT
New Gerrit change created: https://git.eclipse.org/r/c/equinox/rt.equinox.framework/+/165697
Comment 29 Thomas Watson CLA 2020-07-01 10:44:51 EDT
(In reply to Eclipse Genie from comment #28)
> New Gerrit change created:
> https://git.eclipse.org/r/c/equinox/rt.equinox.framework/+/165697

There are things going on in the PDE code that I don't fully comprehend.  I do think it is not ideal that PDE places entries in the dev.properties for which will be on the Bundle-ClassPath header at runtime when in dev mode.

I am not sure I can recommend a good path forward to fix that in PDE without really digging into the PDE code.  For now I decided it is easy enough to detect the duplicates in the DevClassLoadingHook in the framework.

Could someone try out that patch to see if it fixes your issues in PDE.  I still need to add a testcase in Equinox before I will merge.
Comment 30 Julian Honnen CLA 2020-07-02 03:12:55 EDT
(In reply to Thomas Watson from comment #29)
> Could someone try out that patch to see if it fixes your issues in PDE.  I
> still need to add a testcase in Equinox before I will merge.
It does. The testcase from comment 17 has only one dummy.resource on the classpath.
Comment 32 Thomas Watson CLA 2020-07-02 09:25:27 EDT
(In reply to Eclipse Genie from comment #31)
> Gerrit change
> https://git.eclipse.org/r/c/equinox/rt.equinox.framework/+/165697 was merged
> to [master].
> Commit:
> http://git.eclipse.org/c/equinox/rt.equinox.framework.git/commit/
> ?id=d5a30b98485696d2234fef700bc2eaacdaacd599

With this I think we are "fixed" but has that feeling of wallpapering over the issue in PDE's management of the dev.properties for this case.  I'll leave open for others to decide if more work can be done in PDE land.
Comment 33 Julian Honnen CLA 2020-07-03 04:26:04 EDT
(In reply to Thomas Watson from comment #32)
> With this I think we are "fixed" but has that feeling of wallpapering over
> the issue in PDE's management of the dev.properties for this case.  I'll
> leave open for others to decide if more work can be done in PDE land.
Thanks Thomas. I've opened bug 564894 for this follow-up.
Comment 34 Vikas Chandra CLA 2020-07-07 04:14:03 EDT
Julian, can you please verify the bug.
Comment 35 Julian Honnen CLA 2020-07-07 06:30:31 EDT
verified comment 17 with I20200706-2300