Build your very own OSGi applications using the flexible and powerful Felix Framework
The command syntax for the shell interface is based on the Tiny Shell Language (TSL) . It is simple enough to allow a lightweight implementation, yet provides features such as pipes, closures, variable setting and referencing, collection types such as lists and maps, and so on.
The TSL syntax allows the creation of scripts that can be executed by the shell runtime service. The introduction you will get here does not cover the complete syntax; instead, you will see the basic parts of it.
For a review of the proposal in its initial state, (http://www.osgi.org/download/osgi-4.2-early-draft.pdf). You may also refer to the RFC 147 Overview on the Felix documentation pages (http://felix.apache.org/site/rfc-147-overview.html) for potential differences with the initial draft .
A program is a set of chained execution blocks. Blocks are executed in parallel, and the output of a block is streamed as input to the next. Blocks are separated by the pipe character ( | ). Each block is made up of a sequence of statements, separated by a semicolon ( ; ).
For example, as we’ll see in the next section, the bundles command lists the currently installed bundles and the grep command takes a parameter that it uses to filter the input. The program below:
bundles | grep gogo
is made of two statement blocks, namely, bundles and grep gogo. The output of the bundles statement will be connected to the input of the grep gogo statement (here each the statement block contains one statement).
Running this program on your Felix installation, in the state it is now, will produce:
g! bundles | grep gogo
2|Active | 1|org.apache.felix.gogo.command (0.6.0)
3|Active | 1|org.apache.felix.gogo.runtime (0.6.0)
4|Active | 1|org.apache.felix.gogo.shell (0.6.0)
true
The grep statement has filtered the output of the bundles statement for lines containing the filter string gogo. In this case, the grep statement outputs the results of its execution to the shell which prints it.
Executing the statement grep gogo on its own, without a piped block that feeds it input, will connect its input to the user command line. In that case, use Ctrl-Z to terminate your input:
g! grep gogo
line 1
line 2 gogo
line 2 gogo
line 3
^Z
true
Notice that line 2 gogo is repeated right after you have entered it, showing that the grep statement is running in parallel. It receives the input and processes it right after you enter it.
A session variable is assigned a value using the equal character ( = ) and referenced using its name preceded with a dollar character ( $ ). For example:
g! var1 = ‘this is a string’
this is a string
g! echo $var1
this is a string
The assignment operation returns the assigned value.
We’ve seen the string type previously, which is indicated by surrounding text with single quotes ( ‘ ).
A list is a sequence of terms separated by whitespace characters and is delimited by an opening and a closing square bracket.
For example:
g! days = [ mon tue wed thu fri sat sun ]
mon
tue
wed
thu
fri
sat
sun
Here the variable, days, was created, assigned the list as a value, and stored in the session.
A map is a list of assignments, the value is assigned to the key using the equal character ( = ) . For example:
For example:
g! sounds = [ dog=bark cat=meow lion=roar ]
dog bark
cat meow
lion roar
Here, the variable sounds is assigned a map with the preceding key value pairs.
The shell uses a mapping process that involves reflection to find the best operation to perform for a request. We’re not going to go into the details of how this happens; instead, we’ll give a few examples of the operations that can be performed. We’ll see a few others as we go along.
In the same session, days and sounds are defined previously to retrieve an entry in the $days list:
g! $days get 1
tue
To retrieve an entry in the sounds map
g! $sounds get dog
bark
An example we’ve seen earlier is the bundles command used when illustrating the piping. Bundles was mapped to the method getBundles() from the Gogo Runtime bundle BundleContext instance. Another property of this object that we’ll use in the next section is bundle <id> to get a bundle object instance using getBundle(long).
Similar to the UNIX back-quote syntax, but providing one that’s simpler for a lightweight parser, the execution quotes are used to return the output of an executed program.
For example:
g!(bundle 1) location
file:/C:/felix/bundle/org.apache.felix.bundlerepository-1.6.2.jar
Here, (bundle 1) has returned the bundle with ID 1, which we’ve re-used to retrieve the property location making use of Gogo’s reflexion on beans (location is mapped to getLocation() on the Bundle object ).
The Gogo Runti me command processor is extensible and allows any bundle to register the commands it needs to expose to the user. Then, when the user types a command, the processor will attempt to find the method that’s best fit to be executed, based on the command name and passed arguments.
However, there are potential cases where two bundles would need to register the same command name. To avoid this clash, commands are registered with an opti onal scope. When there is no ambiguity as to which scope the command belongs to, the command can be used without a scope; otherwise, the scope must be included.
The scope of a command is specified by pre-pending it to the command, separated from the command with a colon ( : ). In the previous examples, we’ve used the grep command, which is in the gogo scope. In this case, grep and gogo:grep achieve the same result.
We will look closer at the command registration mechanism.
Let’s take a tour of some of the commands available in the Felix distribution.
At the time of writing of this article, the Gogo bundles are at version 0.6.0, which means that they are not yet finalized and may change by the time they are released with version 1.0.
One of the many powerful features of Felix (and OSGi-compliant applications in general) is that many actions can be applied on bundles without needing to restart the framework. Bundles can be installed, updated, uninstalled, and so on while the remaining functionality of the framework is active.
The following are some of the available commands and a description of their usage. We will get to use many of those as we go along, so you need not worry much about learning them by heart. Just know they exist.
One of the most frequently used shell commands is the list bundles command (lb) , which gives a listing of the currently installed bundles, showing some informationon each of them.
Let’s check what’s running on our newly installed framework:
g! lb
START LEVEL 1
ID|State |Level|Name
0|Active | 0|System Bundle (3.0.1)
1|Active | 1|Apache Felix Bundle Repository (1.6.2)
2|Active | 1|Apache Felix Gogo Command (0.6.0)
3|Active | 1|Apache Felix Gogo Runtime (0.6.0)
4|Active | 1|Apache Felix Gogo Shell (0.6.0)
The listing provides the following useful information about each bundle:
This command also takes a parameter for filtering the bundles list. For example, to include only bundles that have ‘bundle’ in their name:
g! lb bundle
START LEVEL 1
ID|State |Level|Name
0|Active | 0|System Bundle (3.0.1)
1|Active | 1|Apache Felix Bundle Repository (1.6.2)
The help command provides hints on the usage of commands.
When called without any parameters, the help command gives a listing of the available commands:
g! help
felix:bundlelevel
felix:cd
felix:frameworklevel
felix:headers
felix:help
felix:inspect
felix:install
felix:lb
felix:log
felix:ls
felix:refresh
felix:resolve
felix:start
felix:stop
felix:uninstall
felix:update
felix:which
gogo:cat
gogo:each
gogo:echo
gogo:format
gogo:getopt
gogo:gosh
gogo:grep
gogo:not
gogo:set
gogo:sh
gogo:source
gogo:tac
gogo:telnetd
gogo:type
gogo:until
obr:deploy
obr:info
obr:javadoc
obr:list
obr:repos
obr:source
More help on the syntax of each command can be requested by typing help <command-name>.
For example, for more help on the repos command:
g! help repos
repos – manage repositories
scope: obr
parameters:
String ( add | list | refresh | remove )
String[] space-delimited list of repository URL
When the command is available with multiple signatures, a help block per signature is provided, for example:
g! help help
help – displays information about a specific command
scope: felix
parameters:
String target command
help – displays available commands
scope: felix
Here, the help command has 2 syntaxes: one that takes a parameter (the target command), and another that takes no parameters. We’ve used the first one to get help on help.
Some commands may have not registered help content with the shell service. Those will show minimal information using help <command>. In most cases, they expose a separate help listing—usually <command> -? or <command> — help.
The install command is used to instruct Felix to install an external bundle. The syntax is as follows:
g! help install
install – install bundle using URLs
scope: felix
parameters:
String[] target URLs
Each bundle is located using the URL and is downloaded to the local cache for installation.
Once a bundle is installed, it is given a unique id. This ID is used to refer to this bundle when using commands such as update or uninstall. For example:
g! install http://www.mysite.com/testbundle-1.0.0.jar
Bundle ID: 7
Here, the bundle I’ve just installed has the ID 7.
g! lb
START LEVEL 1
ID|State |Level|Name
0|Active | 0|System Bundle (3.0.1)
1|Active | 1|Apache Felix Bundle Repository (1.6.2)
2|Active | 1|Apache Felix Gogo Command (0.6.0)
3|Active | 1|Apache Felix Gogo Runtime (0.6.0)
4|Active | 1|Apache Felix Gogo Shell (0.6.0)
7|Installed | 1|Test Bundle (1.0.0)
In cases where many bundles are to be installed from the same base URL, you may want to set a session variable with the common base URL to simplify the task.
For example, instead of executing:
g! install http://site.com/bundle1.jar http://site.com/bundle2.jar
You would write:
g! b = http://site.com
g! install $b/bundle1.jar $b/bundle2.jar
I remember deciding to pursue my first IT certification, the CompTIA A+. I had signed…
Key takeaways The transformer architecture has proved to be revolutionary in outperforming the classical RNN…
Once we learn how to deploy an Ubuntu server, how to manage users, and how…
Key-takeaways: Clean code isn’t just a nice thing to have or a luxury in software projects; it's a necessity. If we…
While developing a web application, or setting dynamic pages and meta tags we need to deal with…
Software architecture is one of the most discussed topics in the software industry today, and…