0

Can someone please provide a working example on how to execute OSGI console commands programmatically?

I am loading OSGI through code and I want to execute OSGI console commands (I am receiving the commands through a different system). This is what I am doing as a simple test:

ServiceLoader<FrameworkFactory> frameworkFactoryService = ServiceLoader.load(FrameworkFactory.class);
FrameworkFactory frameworkFactory = frameworkFactoryService.iterator().next();

Map<String, String> config = new HashMap<String,String>();
config.put("org.osgi.framework.storage", "../workspace/.config");
config.put("org.osgi.framework.storage.clean", "onFirstInit");

framework = frameworkFactory.newFramework(config);

framework.init();
framework.start();  

// install required bundles
String bundleLocation = "org.eclipse.equinox.common_3.8.0.20181108-1144.jar";
Bundle bundle = framework.getBundleContext().installBundle(bundleLocation);

bundleLocation = "org.eclipse.update.configurator_3.4.2.M20090103-1001-RCP20181108-1144.jar";
bundle = framework.getBundleContext().installBundle(bundleLocation);
bundle.start();

bundleLocation = "org.apache.felix.gogo.runtime_0.10.0.v201209301036.jar";
bundle = framework.getBundleContext().installBundle(bundleLocation);
bundle.start();

bundleLocation = "org.apache.felix.gogo.command_0.10.0.v201209301215.jar";
bundle = framework.getBundleContext().installBundle(bundleLocation);
bundle.start();

bundleLocation = "org.apache.felix.gogo.shell_0.10.0.v201212101605.jar";
bundle = framework.getBundleContext().installBundle(bundleLocation);
bundle.start();

bundleLocation = "org.eclipse.equinox.console_1.1.200.v20150929-1405.jar";
bundle = framework.getBundleContext().installBundle(bundleLocation);
bundle.start();

CommandProcessorImpl commandProcessor = new CommandProcessorImpl();
CommandSession commandSession = commandProcessor.createSession(System.in, System.out, System.err);

commandSession.execute("ss");

Everything loads correctly and if I loop through all bundles programmatically I can see everything is loaded and started. Unfortunately I am getting Exception "Command not found: ss" on the "execute" line. What am I doing wrong? Anyone with a simple working example?

user2287359
  • 497
  • 1
  • 5
  • 16

1 Answers1

3

You are starting the CommandProcessImpl yourself. You should get the CommandProcessor service instead. The instance you created has no connection to the framework and can therefore not find any commands registered as services.

 BundleContext context = framework.getBundleContext();
 ServiceReference<CommandProcessor> cpr = 
     context.getServiceReference(CommandProcessor.class);
 CommandProcessor cp = context.getService(cpr);

 CommandSession session = cp.createSession(System.in, System.out, System.err);

 session.execute("lsb");

Clearly this code is not protected. Getting a service reference and then getting a service is really bad since services can come and go.

bnd has a remote agent (biz.aQute.bnd.remote) that you can easily call from an external process. It also has a bndremote program that you can run on any machine and then you can download the framework + bundles in that machine. This might be easier than building this yourself?

Peter Kriens
  • 15,196
  • 1
  • 37
  • 55
  • Thanks. This was a good guidance. I was missing the connection between the framework and the CommandProcessor as this post suggested. I also had to use Reflection as my code is running outside the OSGI environment and had to use classes from packages inside bundles during runtime. I will take a look at bnd as well. – user2287359 Jun 18 '19 at 18:26
  • If you want commands, register a service through the framework. It will be picked up. Much of what you want to do has been done a lot of times in many different settings. Unless this is a hobby project, get some help to not reinvent the wheel, and worse, make the many mistakes in this error prone field. Launchers are complicated! – Peter Kriens Jun 19 '19 at 10:20