The bndlib offers various ways to build better OSGi bundles, this is used in
- felix-bundle-plugin
- bnd-maven-plugin
- Tycho
- bndtools
- PDE itself
- ...
This plugin offers a set of reusable UI components for these usecase to be integrated with Eclipse IDE in a way that is not specific to a given tooling (e.g. PDE, bndtools, m2e, ...) and therefore can be shared across these to prevent duplicate efforts, see here for more details.
One problem for such a reusable component is that it usually needs to get holds of some objects in an specific way that is specific to a given tooling. To mitigate we use the Eclipse Adapter Pattern as it is widely used in Eclipse, flexible and allows the use of OSGi services / Dependency Injection already.
Components need to learn the project and workspace of a bndlib backed project, for this the very first step for an integration is to provide an adapter that can
transform an (Eclipse) IProject
into a (bndlib) Project
(from were the Workspace then can be derived), an example might look like this:
@Component
@AdapterTypes(adaptableClass = IProject.class, adapterNames = Project.class)
public class BndProjectAdapter implements IAdapterFactory {
@Override
public <T> T getAdapter(Object adaptableObject, Class<T> adapterType) {
if (adaptableObject instanceof IProject eclipseProject) {
if (adapterType == Project.class) {
//... here we need to determine if the project is managed by our tooling, e.g. it is a PDE, Bndtool, Maven, ... backed project
if (/*... is relevant ... */) {
// if that is the case, setup a Project that represent your tooling specific setup and return it
Project bndProject = ... fetch or setup a project that maps to the given eclipse project...
return adapterType.cast(bndProject);
}
}
}
return null;
}
}
For some cases one would need to get hold of a Bndrun
(e.g. for launching tests), to support this similar is needed as to create a template that then can further be customized.
For this use-case it is required to provide an adapter that can transform an (Eclipse) IProject
into a (bndlib) Bndrun
that is initialized with the runrequires contain the identity
of the project and the workspace be able to resolve such bundle.
@Component
@AdapterTypes(adaptableClass = IProject.class, adapterNames = Bndrun.class)
public class BndRunAdapter implements IAdapterFactory {
@Override
public <T> T getAdapter(Object adaptableObject, Class<T> adapterType) {
if (adaptableObject instanceof IProject eclipseProject) {
if (adapterType == Project.class) {
//... here we need to determine if the project is managed by our tooling, e.g. it is a PDE, Bndtool, Maven, ... backed project
if (/*... is relevant ... */) {
Workspace workspace = .... find the workspace according to your tooling implementation
Path base = workspace.getBase().toPath();
Path file = Files.createTempFile(base, project.getName(), ".bndrun");
file.toFile().deleteOnExit();
Files.createDirectories(file.getParent());
Properties properties = new Properties();
String bsn = ... derive the symbolic name ...
String version = ... derive the version name ...
properties.setProperty(Constants.RUNREQUIRES, String.format("bnd.identity; id=%s;version=%s", bsn, version));
//maybe more customizations....
Bndrun bndrun = Bndrun.createBndrun(workspace, file.toFile());
//make sure the file is deleted when the bndrun is closed...
bndrun.addClose(new AutoCloseable() {
@Override
public void close() throws Exception {
Files.delete(file);
}
});
}
}
}
return null;
}
}
Beside some integration stuff (e.g. enable to discover bndlib plugins inside an OSGi runtime) it currently offers these components:
- bnd templates
- osgi repositories view
- Formating of bnd files, quick fixes, completion proposals
- ... more to come ...