osgiapache-felixgogo-shell

Execute OSGI console commands programmatically


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?


Solution

  • 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?