Shell GUI

Release version: 1.0.0 - June 13, 2004

Overview

The Shell GUI bundle provides a framework for creating GUI plugins to interact with the Oscar OSGi framework implementation. Taken by itself, the Shell GUI bundle has very little functionality; its only functionality is to listen for Plugin services to arrive and depart and to provide access to individual Plugin GUIs. As such, nearly all functionality for the Shell GUI bundle comes from the Plugin services that it hosts. The Shell Plugin bundle provides plugins for viewing the list of installed bundles, accessing Oscar's shell service, and accessing Oscar's bundle repository. The remainder of this document describes the Plugin service and gives an example of how to create one.

Plugin Interface

To provide an extensibility mechanism, the Shell GUI introduces a simple service interface, called Plugin. Any service implementing this interface will automatically be incorporated into the Shell GUI at run time so that the user can interact with it. The Plugin interface is:


    public interface Plugin
    {
        public String getName();
        public Component getGUI();
    }

The getName() method returns the name of the plugin and this will be used by ShellGUI when presenting the list of available plugins. The getGUI method returns the GUI of the plugin; this method is not a factory method, it should always return the same instance of the GUI each time it is called.

Plugin Example

The example included in this section is very simplistic and is only a intended as a "Hello, world!" example; in other words, it does not do anything useful. The following class implements a plugin by extending JPanel and adding a text field and button to it. When the button is pressed, the plugin will try to install a bundle using the text field value as the location of the bundle.


package test;

import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;

import org.osgi.framework.BundleContext;
import org.ungoverned.osgi.bundle.shellgui.Plugin;

public class InstallerPlugin extends JPanel implements Plugin
{
    private BundleContext m_context = null;
    private JTextField m_textField = null;
    private JButton m_installButton = null;

    // Plugin interface methods.

    public String getName()
    {
        return "Installer";
    }

    public Component getGUI()
    {
        return this;
    }

    // Implementation.

    public InstallerPlugin(BundleContext context)
    {
        m_context = context;
        add(m_textField = new JTextField(30));
        add(m_installButton = new JButton("Install"));

        m_installButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent event)
            {
                if (m_textField.getText().length() > 0)
                {
                    try
                    {
                        m_context.installBundle(m_textField.getText());
                        JOptionPane.showMessageDialog(
                            InstallerPlugin.this, "Bundle installed!", "Success",
                            JOptionPane.INFORMATION_MESSAGE);
                    }
                    catch (Exception ex)
                    {
                        JOptionPane.showMessageDialog(
                            InstallerPlugin.this, ex.getMessage(), "Error",
                            JOptionPane.ERROR_MESSAGE);
                    }
                }
            }
        });
    }
}

A bundle activator class is necessary to register the example plugin service. The following bundle activator registers the plugin service in its start() method. Note: You do not need one activator per plugin, a single activator can register any number of plugins.


package test;

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;

public class Activator implements BundleActivator
{
    private transient BundleContext m_context = null;

    public void start(BundleContext context)
    {
        m_context = context;

        // Register the plugin service.
        m_context.registerService(
            org.ungoverned.osgi.bundle.shellgui.Plugin.class.getName(),
            new InstallerPlugin(m_context), null);
    }

    public void stop(BundleContext context)
    {
        // Services are automatically unregistered so
        // we don't have to unregister the plugin here.
    }
}

To compile these classes you will need to have the Shell GUI bundle JAR file on your class path, as well as the osgi.jar file. Compile these the source files using a command like:


    java -cp -d c:\classes *.java

This command compiles all of the source files and outputs the generated class files into a subdirectory of the c:\classes directory, called test, named after the package of the source files; for the above command to work, the c:\classes directory must exist. Once you have compiled all of the above classes, you need to create a bundle JAR file of the generated package directory. The bundle JAR file needs a manifest, so create a file called manifest.mf with the following contents:


Bundle-Name: Install Plugin
Bundle-Description: A very simple plugin.
Bundle-Activator: test.Activator
Bundle-ClassPath: .
Import-Package: org.ungoverned.osgi.bundle.shellgui

To create the bundle JAR file, issue the command:


    jar cfm installerplugin.jar manifest.mf -C c:\classes test

This command creates a JAR file using the manifest you created and includes all of the classes in the test directory inside of the c:\classes directory. Once the bundle JAR file is created, you are ready to use the plugin. Simply start Oscar and the Shell GUI bundle and then install and start your new plugin bundle; once it starts it will automatically be incorporated into the Shell GUI user interface.

Feedback

If you have comments or suggestions, feel free to contact me at heavy@ungoverned.org.

Richard S. Hall