felix-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From David Savage <dave.sav...@paremus.com>
Subject Visibility semantics
Date Fri, 24 Jul 2009 19:35:48 GMT
Hi there,

Having got some way into getting Sigil up and running on apache, I
think it's useful to start some dialog on it's functionality and
future direction. One of the open areas it would be good to get feed
back from the community is around the problem of class space
visibility and the different semantics at compile and runtime. That's
a bit hard to digest in a single sentence so I'll try to expand on
what this means...

One of the goals of Sigil is to use the same semantics at compile time
as used by OSGi to build a class space at runtime. To this end if you
have a dependency on some package in a certain range in the
sigil.properties file you say things like:

-imports: org.foo.example;version=[1.0.0,2.0.0)

The sigil resolver then walks it's way through the available
repositories to find the "best" bundle that satisfies this import
requirement via an export requirement and this bundle is added to your
classpath. In eclipse we (via the jdt compiler) we have the ability to
apply /real/ osgi rules to this to limit the visibility of other
packages not explicitly imported so you get nice red warning signals
in the IDE if you then reference another class from a different
package that you have not yet imported.

All good.

Where this breaks down with respect to the compiler is if you have a
class hierarchy as follows:

package org.foo;
public interface Top {
  public void doit();
}

package org.foo.example;
public interface Middle extends Top {
}

package org.bar.example {

import org.foo.example.Middle;

public class Other {
  public void broken() {
     Middle m = findMiddle();
     m.doit();
  }

  private Middle findMiddle() {
    // TODO find middle
    return null;
  }
}

If foo and bar are in different bundles and the bar bundle only
imports the org.foo.example package (which is all that is necessary at
runtime) this fails at compile time even if both packages are exported
from foo if we apply the OSGi rules exactly as stated above - as the
compiler needs visibility of the org.foo.Top class in order to know
that the doit() method exists. This is not required at runtime as the
org.foo bundle classloader does have visiblity of the Top class so it
can do the instantiation and hand the resultant object to org.bar.

The solution we've applied in Sigil up until this point is to add an
extra attribute to imports "resolve=compile":

-imports: \
  org.foo;version=[1.0.0,2.0.0);resolve=compile, \
  org.foo.example;version=[1.0.0,2.0.0)

This tells Sigil to make the package available for compilation but
removes the header from the manifest at runtime - as extra
dependencies are bad (standard OSGi mantra). *Note* we also discussed
whether to make this resolution=compile to match the OSGi semantic of
resolution=optional. However we decided to use a different tag as this
would actually be adding our own custom extensions to the OSGi spec
which is also generally viewed as bad...the counter argument to this
is you could say that the OSGi spec is a runtime spec and doesn't
touch on building (yet) so why not extend it?

However this is not the only problem, fragments also cause there own
unique problems to compilation. Consider that the org.eclipse.swt
bundle /claims/ to export a set of packages org.eclipse.swt,
org.eclipse.swt.image, etc. But in actual fact the packages are not
contained in this bundle but are attached via platform specific
fragments org.eclipse.swt.macosx...At runtime this is all fine if you
just specify import package or require bundle then you get the correct
behaviour if the fragment is loaded. However at compile time this puts
an implicit dependency on /some/ fragment to be available to the
compiler to provide the classes. One potential solution for this I've
mentioned here:

https://issues.apache.org/jira/browse/FELIX-1407

This would allow the sigil.properties file to have a compile only
Requires-Bundle dependency on a fragment that would make the classes
visible but this would get stripped from the manifest at runtime so
the bundle would function as normal. *Note* this is also a "live"
problem for the conversion of Sigil to be self hosting as it depends
on the SWT classes so has this exact problem. I have the current
compilation working by adding the requirement for the fragment.
However this causes the bundle to fail to deploy at runtime in
environments that do not have this fragment (i.e. windows, linux etc
:(

To lay my cards on the table, I kinda like resolve=compile as it dove
tails kinda neatly with resolution=optional, but equally it seems
kinda bizarre to be adding another dimension to this whole problem
when people are worried about the complexity of OSGi. If there is a
way to do this without exposing developers to it that would be /great/
but as with OSGi I don't think we should worry about doing the right
thing at the base layer IDE tools and other schemes can always
simpilify this whole space down again to joe blogs. I guess it's a
question of what is "right".

So I guess the end result of this email is, what are your thoughts?

* Is resolve=compile a good idea?
* Should it be resolution=compile?
* Any other options?
* What to do about fragments?
* Is anyone still there (i.e. has this email lost you all?)?

Regards,

Dave

Mime
View raw message