Skip to content
This repository has been archived by the owner on Dec 9, 2018. It is now read-only.

Commit

Permalink
[auxiliary] Allow bnd to load plugins from OSGi
Browse files Browse the repository at this point in the history
This patch allows bndlib to load plugins from OSGi. Any exported package that specifies ‘bnd-plugins=true|range’ and that matches the optional range for the bnd version is added to the Dynamic Imports of bndlib

Signed-off-by: Peter Kriens <peter.kriens@aqute.biz>
  • Loading branch information
pkriens committed Jul 31, 2015
1 parent 31505ac commit 1e5e72d
Show file tree
Hide file tree
Showing 5 changed files with 199 additions and 2 deletions.
148 changes: 148 additions & 0 deletions bndtools.core/src/bndtools/central/Auxiliary.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
package bndtools.central;

import java.io.Closeable;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import java.util.concurrent.atomic.AtomicBoolean;

import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.ServiceRegistration;
import org.osgi.framework.hooks.weaving.WeavingHook;
import org.osgi.framework.hooks.weaving.WovenClass;
import org.osgi.framework.wiring.BundleWiring;
import org.osgi.util.tracker.BundleTracker;

import aQute.bnd.header.Attrs;
import aQute.bnd.header.Parameters;
import aQute.bnd.osgi.About;
import aQute.bnd.osgi.Constants;
import aQute.bnd.osgi.Verifier;
import aQute.bnd.version.Version;
import aQute.bnd.version.VersionRange;

/**
* This class extends the dynamic imports of bndlib with any exported package from OSGi that specifies a 'bnd-plugins'
* attribute. Its value is either true or a version range on the bnd version.
*/
class Auxiliary implements Closeable, WeavingHook {
private final BundleContext context;
private final AtomicBoolean closed = new AtomicBoolean(false);
private final ServiceRegistration<WeavingHook> hook;
private final BundleTracker<Bundle> tracker;
private Bundle bndlib;
private List<String> delta = new ArrayList<>();

Auxiliary(BundleContext context, Bundle bndlib) {
this.bndlib = bndlib;
this.context = context;
this.tracker = new BundleTracker<Bundle>(context, Bundle.RESOLVED + Bundle.ACTIVE + Bundle.STARTING, null) {
@Override
public Bundle addingBundle(Bundle bundle, BundleEvent event) {
if (!doImport(bundle.getHeaders().get(Constants.EXPORT_PACKAGE)))
return null;

return super.addingBundle(bundle, event);
}

};
this.tracker.open();
this.hook = this.context.registerService(WeavingHook.class, this, null);
}

/*
* Parse the exports and see
*
*/
private boolean doImport(String exports) {
if (closed.get() || exports == null || exports.isEmpty())
return false;

Parameters out = new Parameters();

Parameters p = new Parameters(exports);
for (Entry<String,Attrs> e : p.entrySet()) {
Attrs attrs = e.getValue();
if (attrs == null)
continue;

String plugins = attrs.get("bnd-plugins");
if (plugins == null)
continue;

if (!(plugins.isEmpty() || "true".equalsIgnoreCase(plugins))) {
if (Verifier.isVersionRange(plugins)) {
VersionRange range = new VersionRange(plugins);
if (!range.includes(About._3_0)) // TODO
continue;
}
}

//
// Ok, matched
//

String v = attrs.getVersion();
if (v == null)
v = "0";

for (Iterator<String> i = attrs.keySet().iterator(); i.hasNext();) {
String key = i.next();
if (key.endsWith(":"))
i.remove();
}

if (Verifier.isVersion(v)) {
Version version = new Version(v);
attrs.put("version", new VersionRange(true, version, version, true).toString());
}
out.put(e.getKey(), attrs);
}
if (out.isEmpty())
return false;

String imports = out.toString();
synchronized (this) {

if (delta == null)
delta = new ArrayList<>();

delta.add(imports);
}
return true;
}

@Override
public void weave(WovenClass wovenClass) {
if (delta == null || delta.isEmpty())
return;

BundleWiring wiring = wovenClass.getBundleWiring();
if (wiring == null)
return;

if (wiring.getBundle() != bndlib)
return;

List<String> extra;
synchronized (this) {
extra = delta;
delta = null;
}
if (extra != null)
wovenClass.getDynamicImports().addAll(extra);
}

@Override
public void close() throws IOException {
if (closed.getAndSet(true) == false) {
hook.unregister();
tracker.close();
}
}

}
23 changes: 23 additions & 0 deletions bndtools.core/src/bndtools/central/Central.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,14 @@
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;

import aQute.bnd.build.Project;
import aQute.bnd.build.Workspace;
import aQute.bnd.build.WorkspaceRepository;
import aQute.bnd.header.Attrs;
import aQute.bnd.osgi.Constants;
import aQute.bnd.osgi.Processor;
import aQute.bnd.service.Refreshable;
Expand All @@ -58,6 +60,8 @@ public class Central implements IStartupParticipant {
static WorkspaceR5Repository r5Repository = null;
static RepositoryPlugin workspaceRepo = null;

private static Auxiliary auxiliary;

static final AtomicBoolean indexValid = new AtomicBoolean(false);

private final BundleContext bundleContext;
Expand All @@ -66,6 +70,16 @@ public class Central implements IStartupParticipant {

private RepositoryListenerPluginTracker repoListenerTracker;

static {
try {
BundleContext context = FrameworkUtil.getBundle(Central.class).getBundleContext();
Bundle bndlib = FrameworkUtil.getBundle(Workspace.class);
auxiliary = new Auxiliary(context, bndlib);
} catch (Exception e) {
// ignore
}
}

/**
* WARNING: Do not instantiate this class. It must be public to allow instantiation by the Eclipse registry, but it
* is not intended for direct creation by clients. Instead call Central.getInstance().
Expand All @@ -92,6 +106,13 @@ public void stop() {
synchronized (Central.class) {
instance = null;
}

if (auxiliary != null)
try {
auxiliary.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
}

public static Central getInstance() {
Expand Down Expand Up @@ -244,6 +265,8 @@ public synchronized static Workspace getWorkspace() throws Exception {

try {
Workspace.setDriver(Constants.BNDDRIVER_ECLIPSE);
Workspace.addGestalt(Constants.GESTALT_INTERACTIVE, new Attrs());

newWorkspace = Workspace.getWorkspace(getWorkspaceDirectory());

newWorkspace.addBasicPlugin(new WorkspaceListener(newWorkspace));
Expand Down
5 changes: 4 additions & 1 deletion bndtools.jareditor/bnd.bnd
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,7 @@ Conditional-Package: \
Import-Package: org.eclipse.ui*;texteditor=!;ui.workbench=!,\
*

Bundle-Activator: bndtools.jareditor.internal.Plugin
Bundle-Activator: bndtools.jareditor.internal.Plugin

Export-Package: \
bndtools.test.plugin;bnd-plugins=true
21 changes: 21 additions & 0 deletions bndtools.jareditor/src/bndtools/test/plugin/TestPlugin.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package bndtools.test.plugin;

import java.util.Map;

import aQute.bnd.service.Plugin;
import aQute.service.reporter.Reporter;

public class TestPlugin implements Plugin {

@Override
public void setProperties(Map<String,String> map) throws Exception {
System.out.println("Yes, worked!");
}

@Override
public void setReporter(Reporter processor) {
// TODO Auto-generated method stub

}

}
4 changes: 3 additions & 1 deletion bndtools.test/bndws/cnf/build.bnd
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
Foo foo
-include ~${workspace}/cnf/bar.bnd
-include ~${workspace}/cnf/bar.bnd

-plugin.foo = bndtools.test.plugin.TestPlugin

0 comments on commit 1e5e72d

Please sign in to comment.