Tom,

Thanks for the careful responses. I misunderstood the algorithm behind formulating the class path.

You state the algorithm as:

----

1) Search the host bundle; if the entry if found then the search stops; else continue

2) Search each fragment bundle. The fragments are search by bundle ID order; only the first entry found is used.

3) Process each fragment attached ordered by bundle ID order:

3a) For each entry in the fragment Bundle-ClassPath header

3ai) Search only the individual fragment bundle; if found then append to the host's classpath

----

You stated it clearly, but I don't quite see where that algorithm falls out of the specification. (I'm not saying you are wrong, only that I found the specification somewhat vague ;-)

Section 3.8.1 Bundle Class Path gives a single rather straightforward example that I started from in my email.

Section 3.14.2 Fragments During Runtime states only that "A host bundle’s class path is searched before a fragment’s class path. This implies that packages can be split over the host and any of its fragments. Searching the fragments must be done in ascending bundle ID order. This is the order that the fragment bundles were installed."

Furthermore, Section 3.8.4 Overall Search Order is only somewhat illuminating. Step 5 states "The bundle’s own internal bundle class path is searched. If the class or resource is not found, then the search continues with the next step." and Step 6 states "Each attached fragment’s internal bundle class path is searched. The fragments are searched in ascending bundle ID order. If the class or resource is not found, then the search continues with the next step."

The next step(s) in question do not deal with the bundle or fragment class paths.

None of this implied to me that there is a "second pass" through the fragments to process their class paths. If I am missing something else from the spec, or just especially dense please let me know (well, if I'm being dense, please be kind). Otherwise perhaps the spec could be clarified?

Second, I am not clear on one of your responses (the next to last example where you provide your own counter-example). Given:

----
Plugin A_1.0.0.jar:
Bundle-SymbolicName: A
Bundle-Version: 1
Bundle-Classpath: required.jar,optional.jar,default.jar
...contents...
required.jar
default.jar

Plugin B_1.0.0.jar:
Bundle-SymbolicName: B
Bundle-Version: 1
Bundle-Classpath: fragment.jar
Fragment-Host: A
...contents...
optional.jar

Plugin C_1.0.0.jar:
Bundle-SymbolicName: C
Bundle-Version: 1
Fragment-Host: A
...contents...
fragment.jar
----

You stated that:

The effective class path would be:

require.jar (from A), optional.jar (from B), default.jar (from A)

fragment.jar (from C) is not included because we only search B for
fragment.jar, C is not searched for fragment.jar because fragment.jar
is not on the hosts (A) class path or the fragment (C) class path.

However, fragment C does not declare any bundle class path for itself, so should it not default to ".", and so the effective class path would be:

----
require.jar (from A), optional.jar (from B), default.jar (from A), C_1.0.0.jar (from C's ".")?
----

I think I realize the point you were illustrating, but I just want to make sure.

Finally, Equinox supports a public API for resolving dependencies in the package org.eclipse.osgi.service.resolver. Are the algorithms for extracting the class path of a plugin and its fragments available directly from the Equinox resolver without launching an actual runtime? (In my implementation I have to examine the plugin contents to determine if an embedded path/library is in fact available.) Is the same available for evaluating native code libraries?

Thanks in advance and in arrears!

/djk
Message: 1
Date: Fri, 12 Oct 2007 14:55:50 -0500
From: Thomas Watson <[EMAIL PROTECTED]>
Subject: Re: [osgi-dev] bundle class path questions
To: OSGi Developer Mail List <[email protected]>
Message-ID:
<[EMAIL PROTECTED] >
Content-Type: text/plain; charset="us-ascii"

Here are the rules:

For each entry in the host Bundle-ClassPath header:

1) Search the host bundle; if the entry if found then the search stops;
else continue
2) Search each fragment bundle.  The fragments are search by bundle ID
order; only the first entry found is used.
3) Process each fragment attached ordered by bundle ID order:
  a) For each entry in the fragment Bundle-ClassPath header
i) Search only the individual fragment bundle; if found then append to
the host's classpath

See below for the answers using these rules.

Tom



[EMAIL PROTECTED] wrote on 10/10/2007 02:39:30 PM:

> All,
>
> I have some questions regarding bundle class path resolution in the
> presence of fragments. I am not finding the answers obvious from the
> specification.
>
> The example given in 3.8.1 is:
>
> ----
> A: Bundle-SymbolicName: A
>     Bundle-Classpath: required.jar,optional.jar,default.jar
>     content ...
>     required.jar
>     default.jar
> B: Bundle-SymbolicName: B
>     Bundle-Classpath: fragment.jar
>     Fragment-Host: A
>     content ...
>     optional.jar
>     fragment.jar
> ----
>
> and the effective bundle class path is given as
>
> ----
> require.jar, optional.jar, default.jar, fragment.jar
> ----
>
> All well and good. In the example there are no "duplicates" or "."
> defaults. In the following examples I have host A, fragment B, and
> sometimes fragment C. Assume that the fragment B bundle identifier is
> less than C's (i.e. B was installed before C).
>
> 1) What if fragment A is the same, but B is defined as
>
> ----
> B: Bundle-SymbolicName: B
>     Bundle-Classpath: fragment.jar
>     Fragment-Host: A
>     content ...
>     default.jar
>     optional.jar
>     fragment.jar
> ----
>
> (i.e. the fragment also provides "default.jar").
>
> Is the effective bundle class path the same, or does it become
>
> ----
> require.jar, optional.jar (from A), optional.jar (from B),
> default.jar, fragment.jar
> ----
>

I think you mean, will it be (default.jar listed twice not optional.jar):

require.jar (from A), optional.jar (from B), default.jar (from A),
default.jar(from B), fragment.jar (from B)

Only the default.jar from the host bundle will be appended to the
classpath. We stop the search once we have found the host Bundle- ClassPath
entry in the host bundle.  The effective classpath is:

require.jar (from A), optional.jar (from B), default.jar (from A),
fragment.jar (from B)

> In other words, do the fragments augment existing class path entries
> of the host, or does the host always hide an identical fragment
> library if it is also present in the host? If the latter, does this
> shadowing proceed down the ordered list of attached fragments so that > only the first optional.jar encountered becomes part of the effective
> class path?
Only the first optional.jar encountered becomes part of the class path.

>
> 2) Go back to the original spec example. What if host A's bundle
> class path is ".,required.jar,optional.jar,default.jar"?
>
> I assume that this means the first class path entry would be that of
> bundle A's "root".
>
> 2a) Similar to 1), would fragment B's "root" be the second entry?
No, only the first "root" found is used. The root will always be found in
the host.

>
> 2b) If so, then does this imply that a "." in the host plugin "brings
> in" the root of all attached fragments?
No

>
> 2c) If not, does this imply that a "." in the host plugin "hides" "."
> in every attached fragment?

Not really.  The individual Bundle-ClassPath headers of each attached
fragment are processed after the hosts Bundle-ClassPath header has been
processed.  The entries from the fragments Bundle-ClassPath headers
are appended to the effective class path.  When processing fragment
Bundle-ClassPath headers only the fragment with the manifest header
is searched.  Entry names do not collide here between the attached
fragments and their host bundle.  This is because the entries from
fragments are only searched relative to the fragment bundle.


>
> 2d) In any case, is "." special for the host, or does it also apply
> to all fragments (i.e. a fragment including "." in its bundle class
> path effectively brings in the root directory of the host and any
> other fragments)?

No "." in a host will only pull in the "root" content of the host and
"." in the fragment will only pull in the "root" content of the
individual fragment.

>
> 3) Assume again the example from the spec, except that now there is also
>
> ----
> C: Bundle-SymbolicName: C
>     Bundle-Classpath: fragment.jar
>     Fragment-Host: A
>     content ...
>     fragment.jar
> ----
>
> 3a) Does the effective bundle class path become
>
> ----
> require.jar, optional.jar, default.jar, fragment.jar (from B),
> fragment.jar (from C)

Yes

> ----
>
> 3b) If fragment B did *not* actually contain fragment.jar, would the
> effective bundle class path become
>
> ----
> require.jar, optional.jar, default.jar, fragment.jar (from C)
> ----

Yes, but only because C has Bundle-Classpath: fragment.jar

>
> In other words, can a fragment provide "extending" entries to
> declarations made in other fragments?

I think you mean the following case where C does not specify
a Bundle-ClassPath:

> ----
> C: Bundle-SymbolicName: C
>     Fragment-Host: A
>     content ...
>     fragment.jar
> ----

The effective class path would be:

require.jar (from A), optional.jar (from B), default.jar (from A)

fragment.jar (from C) is not included because we only search B for
fragment.jar, C is not searched for fragment.jar because fragment.jar
is not on the hosts (A) class path or the fragment (C) class path.

>
> 4) Now assume:
>
> ----
> A: Bundle-SymbolicName: A
>     Bundle-Classpath: required.jar,optional.jar,default.jar
>     content ...
>     a.jar
> B: Bundle-SymbolicName: B
>     Bundle-Classpath: b.jar
>     Fragment-Host: A
>     content ...
>     b.jar
>     c.jar
> C: Bundle-SymbolicName: C
>     Bundle-Classpath: c.jar
>     Fragment-Host: A
>     content ...
>     c.jar
> ----
>
> What is the effective bundle class path? Specifically, would fragment > B's c.jar appear in it because fragment C declares it, even though it
> is a "later" fragment.

Effective class path would be

b.jar (from B), c.jar (from C)

In this case require.jar, optional.jar, default.jar are all not found
in the host or any attached fragments.
The c.jar (from B) is not included because it was not included on
the Bundle-ClassPath header of the host or the fragment (B)
The b.jar (from B) is included because B specifies it on its
Bundle-ClassPath.
The c.jar (from C) is included because C specifies it on its
Bundle-Classpath.


> Thanks in advance. Sorry for the length, but I believe that in such
> cases concrete examples are better. (I hope I don't have typos that
> obscure my questions ;-)
>
> /djk

_______________________________________________
OSGi Developer Mail List
[email protected]
http://www2.osgi.org/mailman/listinfo/osgi-dev

Reply via email to