I have an Eclipse feature which includes several bundles. I want to tell p2 to mark one of those bundles as started when the feature is installed. This is possible using the bundles own META-INF/p2.inf like so,
instructions.configure = markStarted(started: true)
but I want to do this at the feature-level rather than the bundle-level (the bundle in question is third-party, and I'd prefer not to modify it in any way, if possible).
Some research has led me to this document which suggests that it should be possible to move the configure instructions to the containing feature's p2.inf. I've tried all the obvious things like,
units.0.id = <bundle symbolic name>
units.0.instructions.configure = \
org.eclipse.equinox.p2.touchpoint.eclipse.markStarted(started: true)
but so far none of the permutations I've tried have any effect: as in nothing happens, the bundle isn't marked as started and no errors are reported).
Any pointers would be very welcome. The is with Eclipse Equinox Galileo (3.5.2) ... answers relating to Helios would also be very useful.
The "units.#." p2.inf entries create a new Installable Unit, they don't modify other existing IUs.
You basically have to create an entire Installable Unit fragment. The fragment has the relevant instructions and attaches to your bundle's IU. Then you need to add a requirement from your feature to this new IU.
PDE/Build does this automatically when building products. You could see the generated p2.inf by creating a little rcp product build which has a start level for your bundle.
The generated p2.inf in a product build will be buildDirectory/features/org.eclipse.pde.build.container.feature/product/p2.inf
Here is an example I modified from a build which sets the start level for org.eclipse.equinox.common
. The $version$
will get replaced by the version from the feature that the p2.inf belongs to. Notice the "hostRequirements", which is specifying the bundle we are a fragment of.
#create a requirement on the IU fragment we are creating
requires.2.namespace=org.eclipse.equinox.p2.iu
requires.2.name=configure.org.eclipse.equinox.common
requires.2.range=[$version$,$version$]
requires.2.greedy=true
#create a IU frament named configure.org.eclipse.equinox.common
units.0.id=configure.org.eclipse.equinox.common
units.0.version=$version$
units.0.provides.1.namespace=org.eclipse.equinox.p2.iu
units.0.provides.1.name=configure.org.eclipse.equinox.common
units.0.provides.1.version=$version$
units.0.instructions.install=installBundle(bundle:${artifact});
units.0.instructions.uninstall=uninstallBundle(bundle:${artifact});
units.0.instructions.unconfigure=setStartLevel(startLevel:-1);markStarted(started:false);
units.0.instructions.configure=setStartLevel(startLevel:2);markStarted(started:true);
units.0.hostRequirements.1.namespace=osgi.bundle
units.0.hostRequirements.1.name=org.eclipse.equinox.common
units.0.hostRequirements.1.range=[3.6.0.v20100503,3.6.0.v20100503]
units.0.hostRequirements.1.greedy=false
units.0.hostRequirements.2.namespace=org.eclipse.equinox.p2.eclipse.type
units.0.hostRequirements.2.name=bundle
units.0.hostRequirements.2.range=[1.0.0,2.0.0)
units.0.hostRequirements.2.greedy=false
units.0.requires.1.namespace=osgi.bundle
units.0.requires.1.name=org.eclipse.equinox.common
units.0.requires.1.range=[3.6.0.v20100503,3.6.0.v20100503]
units.0.requires.1.greedy=false
Answers to questions:
0's, 1's, 2's
These numbers are somewhat arbitrary, they serve only to separate one set of properties (requires
or units
or whatever) from another. The requires
here used a '2' simply because I copied it from a large p2.inf that was generated by pde.build and forgot to change it like I did the units.0.
Is all this necessary?
Yes. The second hostRequirements
on the type=bundle is needed. In Helios, with the exception of translation fragments, only one fragment can be attached to an IU. Generally a default IU is available that sets the default start level for all osgi bundles. In order for the our custom fragment to be chosen over the default one, it must have a higher "specificity" which is the number of satisfied host requirements.
For "install"
units.0.instructions.install=installBundle(bundle:${artifact}); units.0.instructions.uninstall=uninstallBundle(bundle:${artifact});
The instructions.install
and instructions.uninstall
refer to phases of the p2 process. The installBundle
and uninstallBundle
refer to install/uninstall in the OSGi sense. Your bundle must be installed into the OSGi system before you can do anything else. This basically invovles adding it to the config.ini or org.eclipse.equinox.simpleconfigurator/bundles.info files.
Most p2 installs will already contain a default configuration IU that will install and set the default start level (4) for bundles. However, currently only one configuration fragment can be applied to each bundle, so when you add your own like this the default no longer applied to your bundle.
hostRequirements. The installable Unit fragments page just describes what a fragment is with no reference on how to create one. It is biefly mentioned on the Customizing Metadata page, but not explained.
Documentation, there is a bunch of stuff on the wiki under the p2 category. the page on the touchpoint instructions might be interesting. There is some help on help.eclipse.org, but in general, I think this is a bit more advanced that what there is documentation for.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With