Gogo Shell

The Gogo shell is a bash like shell that closely interacts with the OSGi framework. Gogo was designed because there is a need for a service that allows human users as well as well as programs to interact with on OSGi based system with a line based interface: a shell. This shell should allow interactive and string based programmatic access to the core features of the framework as well as provide access to functionality that resides in bundles.

Shells can be used from many different sources it is therefore necessary to have a flexible scheme that allows bundles to provide shells based on telnet, the Java 6 Console class, plain Java console, serial ports, files, etc. Supporting commands from bundles should be made very lightweight and simple as to promote supporting the shell in any bundle.

Using the Shell

The Gogo shell feels very bash like but has a number of differences. Primary, the shell uses plain data objects and their public methods as command names. Instead of coercing everything to strings, the shell actually manipulates objects. It has all the necessary features to program in it like variables and closures.

Let’s explore the shell to show what it can do out of the box. The examples in this OSGi enRoute application note are executed in the OSGi enRoute osgi.enroute.gogo.commands.provider project on Github. If you check out the workspace then you can go to the osgi.enroute.gogo.commands.provider project, double click the bnd.bnd file. You should then resolve it and and then debug it. This should provide you with the following output in the console:

   ___ _ __ |  _ \ ___  _   _| |_ ___
  / _ \ '_ \| |_) / _ \| | | | __/ _ \
 |  __/ | | |  _ < (_) | |_| | |_  __/
  \___|_| |_|_| \_\___/ \__,_|\__\___|


The most simple command is echo which works as expected.

G! echo Hello World
Hello World


In the Eclipse console you can unfortunately not edit the commands. However, you can access the history using the bang (‘!’).

G! !ech
Hello World
G! !1
Hello World

In standard terminals, you can use the cursor keys to move back and forth.


Quoting (double or single) is optional if the word does not contain spaces or some special characters like ‘ ’, ‘;’, and some others. So in this case 2 tokens are passed to echo. Notice that we can quote the two words turning it into a single token:
G! echo Hello                     World
Hello World
G! echo 'Hello                     World'
Hello                     World

Multiple Commands

You can execute multiple commands on a line by separating the commands with a semicolon (';').

G! echo Hello; echo World

Multiple commands can also be separated by a pipe character. In that case the output is the input of the next command. Gogo has a built-in grep command so we can use echo to create output and grep to check the output.

G! echo Hello | grep Hello
G! echo Hello | grep World

IO Redirection

Two built-in commands cat and tac ( tac = reversed cat because it stores) are available to provide file data and store file data. Together with the pipe operator they replace the input and output redirection of the bash shell.

G! echo Hello | tac temp.txt
G! echo World | tac -a temp.txt
G! cat temp.txt


Notice that You can find out about the options of a command by using -? (This is not implemented on commands without options and it is not always consistently implemented:

G! tac -?
Usage: tac \[-al\] \[FILE\]
	-a --append              append to FILE
	-l --list                return List<String>
	-? --help                show help

Built-in Commands

Gogo’s commands are methods on objects. By default Gogo adds all public methods on the java.lang.System class and the public methods on the session’s BundleContext as command. This gives us access to some interesting System functions:

G! currenttimemillis
G! property user.dir
property user.dir
G! nanotime
G! identityhashcode abc
G! property foo FOO
G! property foo
G! gc

More interesting is the fact that the current Bundle Context is also available. This interface has a method getBundles so we can now just get the bundles with the bundles command.

G! bundles
0|Active     |    0|org.eclipse.osgi (3.10.100.v20150529-1857)
1|Active     |    1|org.apache.felix.configadmin (1.8.6)
2|Active     |    1|org.apache.felix.gogo.runtime (0.16.2)
3|Active     |    1|org.apache.felix.log (1.0.1)
4|Active     |    1|org.apache.felix.scr (2.0.0)
5|Active     |    1|org.eclipse.equinox.metatype (1.4.100.v20150408-1437)
6|Active     |    1|org.osgi.service.metatype (
7|Active     |    1|osgi.enroute.gogo.commands.provider (
8|Active     |    1|org.apache.felix.gogo.shell (

We could now also get a specific bundle:

G! bundle 4
Location             reference:file:/...
State                32
Bundle                   4|Active     |    1|org.apache.felix.scr (2.0.0)
Module               osgi.identity; ...
RegisteredServices   [ConfigurationListener, ServiceComponentRuntime, ScrGogoCommand, ManagedService]
ServicesInUse        [LogService]
BundleContext        org.eclipse.osgi.internal.framework.BundleContextImpl@3943a2be
SymbolicName         org.apache.felix.scr
BundleId             4
LastModified         1458156749977
Headers              ...
Version              2.0.0


Notice that neither command required anything special, they are just the methods defined on Bundle Context. The implementation has no clue about Gogo. All these commands return domain plain unadorned objects. We can test this because Gogo has variables that store these plain objects. We can then use those objects in the shell as commands.

G! bundle = bundle 4
G! $bundle tostring
org.apache.felix.scr_2.0.0 [4]
G! $bundle bundleid
G! $bundle headers
Bundle-License      http://www.apache.org/licenses/LICENSE-2.0.txt
Manifest-Version    1.0
Created-By          Apache Maven Bundle Plugin
Bnd-LastModified    1438861013315
Bundle-Name         Apache Felix Declarative Services


Variables can be have any name. They are set with <name>=<expr>. They are referred to by $<name>. Gogo uses variables also itself. For example, the prompt can be changed by setting a new prompt variable.

G! prompt= '$ '

The following variables are in use by the shell:


The syntax feels very natural but there is something a bit tricky going on. The first token in the command can either identify the name of a command or an object. With an object, the next token is the method on that object. This can cause ambiguity. The scope is further discussed later when we add custom commands. Just be aware that the first token is either an object or a command name.


We’ve already use string literals. However, it is also possible to use lists and maps:

G! [1 2 3] size
G! [a=1 b=2 c=3] get b


So how do we access a specific header. A command like $bundle headers get Bundle-Version cannot work because Gogo will see this as one command and will complain with: Cannot coerce headers(String, String) to any of [(), (String)]. The parentheses come to the rescue:

G! $bundle headers get Bundle-Version
Cannot coerce headers(String, String) to any of [(), (String)]
G! ($bundle headers) get Bundle-Version

The parentheses first calculate the expression in their inner bowels which then becomes available as the target object for the remaining command. I.e. ($bundle headers) returns a Dictionary object, which subsequently becomes the target object. The get token is the method called on this target object, with the Bundle-Version as parameter.

Back ticks

The bash shell has this wonderful capability of executing commands to get an argument by placing back ticks around a command. We can use the parentheses for the same effect, with the added benefit that the parentheses work recursively.

G! echo Bundle ($bundle bundleid) has name ((bundle ($bundle bundleid)) symbolicname)
Bundle 4 has name org.apache.felix.scr


The Gogo shell can store commands for later execution. The { and } delimiters are used for that purpose. We can store these functions in objects or pass them as parameters. To execute a function as a command, you should use the name of the variable without the dollar (‘$’) sign.

G! f = { echo Hello }
echo Hello
G! f

You can pass arguments to the function. They are named $1..$9. $0 is the command name if available. The $it macro refers to $1.

G! f = { echo $it }
echo $1
G! f Hello World

Obviously it is not very nice that we miss the World because we only used $1. There is a magic variable called $args. This variable is list that gets expanded into separate arguments. So we can change our function to use all the arguments when the function is invoked:

G! f = { echo $args }
echo $args
G! f Hello         World
Hello World

The $args list of arguments cannot be manipulated as a normal object, it gets expanded into its members wherever you use it.

Repeat and Conditionals

Gogo provides a number of built in commands that use the functions to provide conditional and repeated execution. For example, the each command takes a collection and a function. It then iterates over the collection and calls the function with the element of the iteration.

G! each [1 2 3] { echo -- $it --  }
-- 1 --
-- 2 --
-- 3 --

We can now also use the if command:

G! l = []
G! if {$l isempty} { echo empty } { echo not empty }
G! $l add foo
G! if {$l isempty} { echo empty } { echo not empty }
not empty

You can negate with the not command, which takes a function: G! if { not {$l isempty}} { echo not empty } { echo empty } not empty

TODO while, until


You (and any code you call) can throw exceptions. The last exception is stored in the $exception variable and there is a built in function e that shows the stack trace.

G! throw Foo
G! $exception message
G! e
java.lang.IllegalArgumentException: Foo
at org.apache.felix.gogo.shell.Procedural._throw(Procedural.java:83)

You can also catch the exceptions with a try command.

G! exception = null
G! try { throw Foo }
G! $exception

Of course we now silently ignore the exception, not a good idea. So we can provide a catch function that receives the exception as the $it variable.

G! try { throw Foo } { echo ouch }

Providing a Command

Bundles that can add commands to the shell by registering any service with the osgi.command.scope property and osgi.command.function service properties. The Gogo shell then call any method name listed in the osgi.command.function property. To disambiguate, the osgi.command.scope can be used by prefixing the command with the scope and a ‘:’. The constants for these properties can be found in osgi.enroute.debug.api.Debug.

For example, assume the following component is registered:

	property = {
		Debug.COMMAND_SCOPE + "=hello", //
		Debug.COMMAND_FUNCTION + "=world" //
public class FooImpl implements Foo {

	public void sysout() {
		System.out.println("Hello World");

A primary goal of the design was to make it possible to add commands to existing service implementation objects.

Using the Shell

In the shell, we can now call the function:

G! sysout
Hello World
G! hello:sysout
Hello World

In the example we use System.out. For some surprisingly, this is ok, even if the shell is accessed via SSH or telnet. The Gogo shell redirects System.out for the duration of a command. However, the command is currently not usable for other code. It would be nicer if we could return the text:

public String value() {
	return "Hello World";

No running it in the shell makes it look the same:

G! value
Hello World


We can also provide an argument. Gogo attempts to use a syntax that one expects in a shell but then translate this to method calls. So if we have the command:

public String parameter(String parameter) {
	return "Hello " + parameter;

So let’s try this out:

G! parameter OSGi
Hello OSGi

It is also quite easy to make the parameter an option:

public String option(
		String parameter
	) {
	return "Hello " + parameter;

Since we have an absent value, we do not need the value to be specified. So we can call the command with and without a parameter.

G! option
Hello World
G! option -p OSGi
Hello OSGi
G! option --parameter OSGi
Hello OSGi


So far we have had a 1:1 relation between the command name and the method. However, it was a primary design goal of Gogo to make it feel like a shell but interact seamlessly with standard Java code. In Java we often use design patterns like prefixing the name of a property with get. Gogo will therefore try to match a command to a method removing the prefixes and case sensitivity. So if we add a method getFoo then we can stil call it:

public String getFoo() {
	return "Foo";

We can now call this command in many different ways. G! foo Foo G! FOO Foo G! Foo Foo