aqute osgi bootcamp workshop exercise by peter kriens ceo aqute osgi technology officer and osgi...

Post on 27-Mar-2015

233 Views

Category:

Documents

3 Downloads

Preview:

Click to see full reader

TRANSCRIPT

aQuteOSGi Bootcamp

Workshop Exercise

By Peter KriensCEO aQute

OSGi Technology Officer andOSGi Fellow

©1999-2003 aQute, All Rights Reserved

Setting Up The Environment

• The CD contains all the tools you need:– Java 1.4.1– Eclipse 2.0.2– Exercise projects with source (ex dir)– Framework fwx.exe

• Also available on the network \\ziggy\fwx

• Install Java 1.4.1, Install Eclipse

• Copy the workshop dir to c:\fwx

©1999-2003 aQute, All Rights Reserved

What Will We Do?

• These exercises take a step by step approach to make a larger program

• This program is a “See your buddies” Web page viewer

• Each participant will make a Web page

• This web page is automatically registered with all participants portal's

• With Zero Administration …

©1999-2003 aQute, All Rights Reserved

Overview

app2

app3 app1

app4

Browser

app 1app 2app 3app 4

SP 2

SP 3

SP 4

SP 1

multicast

©1999-2003 aQute, All Rights Reserved

Architecture: Classes

ActivatorDistributor

Link

HttpTrackerTracks httpservers

findsbuddies

<<interface>>Http Service

ServiceTracker

Thread<<interface>>BundleActivator

Tracks buddies Registers page

Portal Tracks portal entries

Registers /portal page

LogService

Logs messages

HttpContext

©1999-2003 aQute, All Rights Reserved

What Will We Learn?

• Using Eclipse

• Constructing an OSGi bundle

• Class path management

• Using the Log service

• Tracking of the Http Services

• Registering a servlet

• Using the demo portal

• Networking code

©1999-2003 aQute, All Rights Reserved

1.1 Hello World Bundle

• Create a simple bundle printing "Hello World" and "Goodbye World" at start and stop

• What will you learn?– Construct a BundleActivator class– Add a correct Manifest– Place it all in a JAR file– Starting the Framework– Install/Uninstall a bundle

©1999-2003 aQute, All Rights Reserved

1.1 Back to Basics: Hello World

Activator

The Activator class will print “Hello World” when the bundle is started and “Goodbye World” when it stops.

<<interface>>BundleActivator

©1999-2003 aQute, All Rights Reserved

1.1 Getting Started

• Assumptions– Eclipse 2.0.2 (check in Help:About, 2.0.0 does not

work!) installed– Started Eclipse

©1999-2003 aQute, All Rights Reserved

1.1 Eclipse

©1999-2003 aQute, All Rights Reserved

1.1 Getting Started

• Create new Java Project– File:New:Project– Java Project, Next– Name is “ws”– Default location, Next– Libraries, Add external jars,

• servlet.jar, osgi.jar (from where you copied the files. c:\fwx\osgi.jar)

– Attach source (select osgi.jar), Finish

©1999-2003 aQute, All Rights Reserved

1.1 Add External Jar

©1999-2003 aQute, All Rights Reserved

1.1 Setup Activator class

• Add Package– File:New:Package– Name, aQute.world.congress

©1999-2003 aQute, All Rights Reserved

1.1 Setup Activator

• Add new class

• File:New:Class– Package, aQute.world.congress– Name, Activator– Interfaces

• Add BundleActivator

• Finish

• Eclipse will open a generated source file

©1999-2003 aQute, All Rights Reserved

1.1 Activator class setup

©1999-2003 aQute, All Rights Reserved

1.1 Write Hello/Goodbye World

• Fill in the System.out.println(“...”) in the appropriate places

• Save the file (File:Save or control-S)– This automatically compiles, so correct any errors

©1999-2003 aQute, All Rights Reserved

1.1 Create The Manifest

• We only define what class to start: Activator

• File:New:File, name it Manifest.mf – Store in aQute.world.congress package/folder

• Manifest MUST end with 2 empty lines!!• Fill in (and save):

Manifest-Version: 1.0Bundle-Activator: aQute.world.congress.Activator

©1999-2003 aQute, All Rights Reserved

1.1 Create Manifest

©1999-2003 aQute, All Rights Reserved

1.1 Create Bundle JAR file!

• Select “ws” in left pane

• Press right mouse button

• Select Export

• Select JAR File

• Next

©1999-2003 aQute, All Rights Reserved

1.1 Create JAR File

• Export Destination– Name it ws.jar– Save the JAR in the load directory

where you copied fwx,e.g. c:\fwx\load

• Next

©1999-2003 aQute, All Rights Reserved

1.1 Create JAR file

• Deselect “with compile errors”

• Save the description in the “ws” workspace, under the name bundle.jardesc

• Next

©1999-2003 aQute, All Rights Reserved

1.1 Create JAR file

• Set to use existing Manifest– Select Manifest.mf

• Finish

• (It is OK to create theload directory)

©1999-2003 aQute, All Rights Reserved

1.1 Starting A Framework

• The fwx.jar is the OSGi Reference Framework with all the R3 services reference implementations– This Framework is not optimized, nor industrialized– It expires in 60 days– Contact a vendor for a real framework

• To start it, open a window on its directory and double click it

• It will automatically start all bundles in the load directory– This is not standard but implemented in a bundle

©1999-2003 aQute, All Rights Reserved

1.1 Starting the Framework

©1999-2003 aQute, All Rights Reserved

1.1 Restarting

• You can restart the bundle by – select the bundle.jardesc– Right mouse: Create Jar

• This works because the fileinstall bundle on the Framework will detect that the JAR file is modified in the load directory

• This will automatically update the bundle in the Framework (look at the console)

©1999-2003 aQute, All Rights Reserved

1.1 What Did We Learn?

• We learned how to create a real bundle

• This bundle needed– An Activator class– A Manifest

• These components were packed in a JAR file

• This JAR file was installed and started on an OSGi Framework with the fileinstaller bundle

• The console was used to see the start and stop methods

©1999-2003 aQute, All Rights Reserved

1.2 Using the Log Service

• Instead of using the console, change the code to use the Log Service from the registry

• What will you learn in this exercise?– Use a service from another bundle– Import packages from another bundle– Get a service from the registry– Use the log service– Find out the methods of a service

©1999-2003 aQute, All Rights Reserved

1.2 Using The Log Service

Activator

We will now use a service: The Log Service

<<interface>>BundleActivator

LogService

Logs messages

©1999-2003 aQute, All Rights Reserved

org.osgi.service.log v1.1Log Service

• Simple and small Log service for operator

• 4 Levels– INFO, DEBUG, WARNING, ERROR

• Automatically logs framework events in a defined way

• Other bundles can access log history– Management bundle– Length implementation dependent

• Used also for accounting, notifications

©1999-2003 aQute, All Rights Reserved

org.osgi.service.log v1.1Log Service

a log usera log user a log readera log reader

LogServiceLogService LogEntryLogEntry LogListenerLogListener LogReaderService

LogReaderService

a log service impl.

a log service impl.

A log entryimpl.

A log entryimpl.

A log readerimpl.

A log readerimpl.

Log Service Impl. bundle

Log a message

Store a message for retrieval and broadcast

Message log

Send new log entry

Retrieve log

A loguser bundle

A logreaderusing bundle

©1999-2003 aQute, All Rights Reserved

1.2 Prepare for the Log Service

• Save the BundleContext parameter in a context instance variable

BundleContext context;public void start(BundleContext context) { this.context = context; ...}

©1999-2003 aQute, All Rights Reserved

1.2 The log() method

• Add a log() method to the Activator class:

void log( String msg, Throwable exception ) { ServiceReference ref = context.getServiceReference( LogService.class.getName() ); LogService log = null; if ( ref != null ) { log =(LogService) context.getService(ref); if ( log != null ) { if ( exception == null ) log.log( LogService.LOG_INFO, msg ); else log.log( LogService.LOG_ERROR, msg, exception ); } context.ungetService(ref); return; } System.out.println( msg + " : " + exception );}

©1999-2003 aQute, All Rights Reserved

1.2 Use the log method

• Replace the calls to System.out with calls to the log() method

public void start(BundleContext context) { this.context = context; log( "Hello world", null );}public void stop(BundleContext context){ log( "Goodbye world", null );}

©1999-2003 aQute, All Rights Reserved

1.2 Organize Imports

• Source:Organize Imports

• This will automatically add the necessary import statements

©1999-2003 aQute, All Rights Reserved

1.2 Contents of LogService

• How can you find out what the LogService can do for you?

– Use the Javadoc (on the CD)– Click on the type, open context menu (right mouse

button) and select "Open Declaration"– Use the Ctrl-Space function in Eclipse

©1999-2003 aQute, All Rights Reserved

1.2 Finding The Methods

Type Ctrl-Space

©1999-2003 aQute, All Rights Reserved

1.2 Importing

• We use the Log Service, this requires the import of the org.osgi.service.log package

• This is indicated in the Manifest file with the Import-Package manifest header

• This header may contain any number of packages, separated with a comma, and optionally with a specification-version modifier

©1999-2003 aQute, All Rights Reserved

1.2 Modify The Manifest

• Edit Manifest.mf

• Add Import-Package for– org.osgi.service.log

Manifest-Version: 1.0Bundle-Activator: aQute.world.congress.ActivatorImport-Package: org.osgi.framework, org.osgi.service.log;specification-version=1.0

©1999-2003 aQute, All Rights Reserved

1.2 Using the Log Service

• Save the source file (correct compile errors)

• Select bundle.jardesc, right menu, Create JAR

• Check the console of fwx:– Goodbye world– But no Hello world … This is now in the log– Where is the log????

©1999-2003 aQute, All Rights Reserved

1.2 Viewing the Log Service

• Open a telnet session– Start:Run:telnet localhost 2011

• This opens a simple OSGi console/debugger

• Type– log

©1999-2003 aQute, All Rights Reserved

1.2 The console

• The console bundle has many functions– exports - shows package export/import– lsb - list bundles– lss - list services (can use filter)– install <uri> - install– uninstall <id>– update bundle <id>– help

• Can be extended by other bundles, see org.osgi.tools.command.CommandProvider

©1999-2003 aQute, All Rights Reserved

1.2 Changing the version

• Verify what happens when the specfication version is modified

• Set the version to 1.8 and create the JAR file

©1999-2003 aQute, All Rights Reserved

1.2 What Did We Learn?

• Using the Log Service

• Importing a package, with version specification

• Getting a service from the registry

• Using the OSGi console bundle

©1999-2003 aQute, All Rights Reserved

1.2a Using the Service Tracker

• Track the OSGi Log Service with a Service Tracker

• What will we learn?

• How to efficiently track a service

• Assure that a temporary absence of a service does not disrupt our program

• The org.osgi.util.tracker.ServiceTracker utility

©1999-2003 aQute, All Rights Reserved

1.2a Use the ServiceTracker

• Create a ServiceTracker for the log

ServiceTracker tracker;

public void start(BundleContext context) { this.context = context; tracker = new ServiceTracker( context,

LogService.class.getName(), null ); tracker.open();}

©1999-2003 aQute, All Rights Reserved

1.2a Use The ServiceTracker

• Change the log() method to use the tracker

void log( String msg, Throwable exception ) { try { LogService log =(LogService) tracker.waitForService(15000); if ( exception == null ) log.log( LogService.LOG_INFO, msg ); else log.log( LogService.LOG_ERROR, msg, exception ); return; } catch ( InterruptedException ie ) {} System.out.println( msg + " : " + exception );}

©1999-2003 aQute, All Rights Reserved

1.2a What Did We Learn?

• We now correctly handling the coming and going of services

• Using a ServiceTracker simplifies the coding of services that are obtained from the registry

• The use of the log is now robust

©1999-2003 aQute, All Rights Reserved

1.3 Using the Http Service

• Register a static HTML page with the local Http Service

• What will we learn?

• Use the ServiceTracker more extensively

• How to register a static HTML page with the Http Service

• How to implement the HttpContext

©1999-2003 aQute, All Rights Reserved

1.3 Publishing a page

HttpTrackerTracks httpservers

<<interface>>Http Service

ServiceTracker

Registers page

Registers /portal page

Activator

<<interface>>BundleActivator

LogService

Logs messages

HttpContext

©1999-2003 aQute, All Rights Reserved

org.osgi.service.http v1.1Http Service

• Provides web access to bundles

• A powerful servlet runner– Supports Servlets Version 2.1

• Very simple to export static pages and files (like images)

• Automatically unregisters servlets when bundle is stopped

©1999-2003 aQute, All Rights Reserved

org.osgi.service.http v1.1Http Service

Impl. Of Httpcontext

Impl. Of Httpcontext

Impl. Of servlet

Impl. Of servlet

HttpContextHttpContext NameSpaceException

NameSpaceException HttpServiceHttpService

javax.servlet.Servlet

javax.servlet.Servlet

Default impl.HttpContext

Default impl.HttpContext

Resourceregistration

Resourceregistration

Servletregistration

Servletregistration

Bundles main code

Bundles main code

javax.servlet.Request/Response

javax.servlet.Request/Response

NameSpacealias

NameSpacealias

An Http Serviceimpl.

An Http Serviceimpl.

©1999-2003 aQute, All Rights Reserved

1.3 Create An Html Page

• File:New:File– Directory, aQute/world/congress– Call it page.html

• Edit it (select page.html, Open With:Text Editor)

<html> <head> <title>My Demo HTML page</title> </head> <body> <h1>My Demo</h1> This is aQute's (use your own name!) demo page </body></html>

©1999-2003 aQute, All Rights Reserved

1.3 Create an HTML Page

©1999-2003 aQute, All Rights Reserved

1.3 Create HttpTracker

• HttpTracker tracks Http Service objects and adds a “page.html” to every Http Service

• It extends ServiceTracker to simplify tracking– Object addingService(ServiceReference)– void modifiedService(ServiceReference,Object)– void removedService(ServiceReference,Object)

• Create new class aQute.world.congress.HttpTracker that extends ServiceTracker, implements HttpContext

©1999-2003 aQute, All Rights Reserved

1.3 Add HttpTracker class

©1999-2003 aQute, All Rights Reserved

1.3 Add HttpTracker class

• And it needs a variable, constructor, add:

Activator activator;

public HttpTracker( Activator activator, BundleContext context ) { super( context, HttpService.class.getName(),null); this.activator = activator;}

©1999-2003 aQute, All Rights Reserved

1.3 Add HttpTracker class

• addingService

public Object addingService( ServiceReference reference ) { HttpService http = (HttpService)super.addingService(reference); try { http.registerResources("/mydemo", "", this ); } catch( NamespaceException e ) { activator.log( "Cannot register because “

+ “name is already in use: /mydemo", e ); } return http;}

©1999-2003 aQute, All Rights Reserved

1.3 Add HttpTracker class

• Modify the getResource method to return resources from the package

public URL getResource(String name) { try { URL url = getClass().getResource( name.substring(1) ); return url; } catch( Exception e ) { e.printStackTrace(); } return null;}

©1999-2003 aQute, All Rights Reserved

1.3 Add HttpTracker class

• handlSecurity returns false. This means deny access, change it to return true.

public boolean handleSecurity( HttpServletRequest request, HttpServletResponse response) throws IOException { return true;}

©1999-2003 aQute, All Rights Reserved

1.3 Add HttpTracker class

• Organize Imports

• Save it

• Add an instance variable for the Http Tracker to Activator class

• And add the following lines to the start() method http = new HttpTracker( this, context );http.open();

HttpTracker http;

©1999-2003 aQute, All Rights Reserved

1.3 Clean-up

// Add to stop methodhttp.close();

©1999-2003 aQute, All Rights Reserved

1.3 Modify The Manifest

• Add Import-Package for– org.osgi.util.tracker– org.osgi.service.http– javax.servlet.http, javax.servlet

Manifest-Version: 1.0Bundle-Activator: aQute.world.congress.ActivatorImport-Package: org.osgi.framework, org.osgi.service.log,org.osgi.util.tracker, org.osgi.service.http,javax.servlet.http, javax.servlet

©1999-2003 aQute, All Rights Reserved

1.3 Add HttpTracker class

• Save open files

• Select bundle.jardesc– Create JAR

• Open a browser and surf into– http://localhost/mydemo/page.html

• Ensure that your HTTP proxy is off!– IE : Tools : Internet Options : Connections : Lan

settings

©1999-2003 aQute, All Rights Reserved

1.3 What Did We Learn?

• Understanding how the ServiceTracker can be used to track services and execute a task for the registration and un-registration of a service

• Understanding the HttpContext

• Serving static pages from the local web server

©1999-2003 aQute, All Rights Reserved

1.3a Use The Portal

• Register our page with a local portal bundle using the white board approach

• What will we learn?

• Using the White Board approach

• Using the provided portal with our page

• Understand service registration properties

©1999-2003 aQute, All Rights Reserved

1.3a Use The Portal

Activator HttpTrackerTracks httpservers

<<interface>>Http Service

ServiceTracker

<<interface>>BundleActivator

Registers page

Portal

Registers /portal page

LogService

Logs messages

HttpContext

©1999-2003 aQute, All Rights Reserved

1.3a The Nursery Portal

• Not an official OSGi specification (Nursery)

• Uses the White Board approach to collect pages

• Properties are used to convey the information

• The portal is not a service in the registry

• Clients should register any service with the right properties

• Minimizes dependencies

©1999-2003 aQute, All Rights Reserved

1.3a Portal Mechanism

Registry

Bundle A{ }

register

Portalbundle

Events: register, unregister

Bundle C{ }

Bundle B{ }

Any objectget

urltitledescription

http://...My PageA demonst...

properties

Filter (url=*)

Properties

©1999-2003 aQute, All Rights Reserved

1.3a Portal

• In the start() method, add the following code:

String host= InetAddress.getLocalHost().getHostName();if ( System.getProperty( "org.osgi.service.http.port" ) != null ) host += ":" + System.getProperty( "org.osgi.service.http.port" );

Dictionary properties = new Hashtable();properties.put( "title", "Local Demo Page" ); properties.put( "description", "This page demonstrates my skills!" );properties.put( "url", "http://" + host + "/mydemo/page.html" );context.registerService( String.class.getName(), "dummy", properties );

©1999-2003 aQute, All Rights Reserved

1.3a Portal

• Verify that your page is registered at the portal– http://localhost:8000/portal

©1999-2003 aQute, All Rights Reserved

1.3a What Did We Learn

• How to register a service

• The ideas behind the white board– Use the Framework registry as a private registry– Minimized dependencies

• Use of the portal

©1999-2003 aQute, All Rights Reserved

1.4 Finding Your Buddies

• Announce the page URL with a multicast on the network and register the received URLs with the portal

• What will you learn?

• How to register a service

• How send out multicast packages

• Using a background thread to receive packages

• Minimize consequences in the light of errors

©1999-2003 aQute, All Rights Reserved

1.4 Finding Your Buddies

HttpTrackerTracks httpservers

<<interface>>Http Service

ServiceTracker

Registers page

Portal

Registers /portal page

Activator

<<interface>>BundleActivator

LogService

Logs messages

Distributor

Link

findsbuddies

Thread

Tracks buddies

Tracks portal entries

HttpContext

©1999-2003 aQute, All Rights Reserved

1.4 Add Distributor class

• Add a new class Distributor– Package aQute.world.congress– Extends Thread

• This class will open a UDP socket

• Will listen to all Datagram’s on port 2014

• Forwards all datagrams to the activator

• Sends an announce datagram every 5 seconds

• Simple mechanism to dynamically discover others

©1999-2003 aQute, All Rights Reserved

1.4 Add Distributor class

• Add Instance variable declarations

boolean active = true;DatagramSocket socket;byte outgoing[];Activator activator;

©1999-2003 aQute, All Rights Reserved

1.4 Add Distributor class

• Add Constructor

Distributor( Activator activator, String outgoing ) { super("distributor"); this.activator = activator; this.outgoing = outgoing.getBytes();}

©1999-2003 aQute, All Rights Reserved

1.4 Add Distributor class

public void run() { while ( active ) try { socket = new DatagramSocket( 2014 ); socket.setSoTimeout( 5000 ); activator.log("Discovery starts.", null); … inner loop … see next slide socket.close(); socket = null; } catch(Exception e) { activator.log( "Main discover loop exit", e ); if ( active ) try { Thread.currentThread().sleep(1000); } catch( Exception x) {} } activator.log("Discovery quits.", null);}

• The run() method is the body of the thread. It will loop until the active flag becomes false. It uses the socket timeout to regularly send an announce

©1999-2003 aQute, All Rights Reserved

• The inner loop of the run() method receives the package and handles errors

1.4 Add Distributor class

while ( active ) try { DatagramPacket packet = new DatagramPacket(new byte[256], 256); socket.receive(packet); String incoming = new String( packet.getData(), 0, packet.getLength()); activator.process( new Link(incoming) ); }catch(InterruptedIOException e) { announce();} catch(Exception e) { if ( active ) activator.log( "Receving remote “ + “service packets, ignoring ", e );}

©1999-2003 aQute, All Rights Reserved

1.4 Add Distributor class

• The announce method is called on the timeout

void announce() throws IOException { DatagramSocket announce = new DatagramSocket(); DatagramPacket packet = new DatagramPacket( outgoing, outgoing.length, InetAddress.getByName("255.255.255.255"), 2014 ); announce.send(packet); }

©1999-2003 aQute, All Rights Reserved

1.4 Add Distributor class

• And the last close method resets the active flag and closes the port.

• Organize imports

• Save– Unresolved method in Activator: process

void close() { active = false; socket.close();}

©1999-2003 aQute, All Rights Reserved

1.4 Add Link class

• Add a Link class

• The Link class just holds the buddy info together.Hashtable properties = new Hashtable();ServiceRegistration registration;

Link( String msg ) { StringTokenizer tz =

new StringTokenizer( msg, "|" ); properties.put( "title", tz.nextToken() ); properties.put( "description",tz.nextToken()); properties.put( "url", tz.nextToken() ); }

©1999-2003 aQute, All Rights Reserved

1.4 Add Link class

• Register method, for a new discovered buddy

• Modify method, when old buddy, new message

void register( BundleContext context ) { registration = context.registerService( Link.class.getName(), this, properties );}

void modify( Link link ) { registration.setProperties(link.properties);}

©1999-2003 aQute, All Rights Reserved

1.4 Add Link class

• Unregister when link is gone

• To get the unique key

void unregister() { registration.unregister();}

Object getUrl(){ return properties.get( "url" ); }

©1999-2003 aQute, All Rights Reserved

1.4 Process method in Activator

• The process method adds a buddy to the portal

• The portal tracks “url” service property.

• Edit Activator, add process methodHashtable links = new Hashtable();void process( Link link ) { Link existing = (Link) links.get( link.getUrl() ); if ( existing != null ) existing.modify( link ); else { link.register( context ); links.put( link.getUrl(), link ); existing = link; }}

©1999-2003 aQute, All Rights Reserved

1.4 Add and Start the Distributor

// Add to start methodString host= InetAddress.getLocalHost().getHostAddress();if ( System.getProperty(

"org.osgi.service.http.port" ) != null )host += ":" + System.getProperty(

"org.osgi.service.http.port" );

distributor = new Distributor( this, "My Title|My Own Description|http://" + host +

"/mydemo/page.html" );distributor.start();

©1999-2003 aQute, All Rights Reserved

1.4 Clean-up (stop method)

// Add to stop methoddistributor.close();

©1999-2003 aQute, All Rights Reserved

1.4 Find the buddies

• Organize imports for all files

• Build JAR

• Browse to:– http://localhost:8000/portal

• You should see your own page, and with any luck pages from your buddies

©1999-2003 aQute, All Rights Reserved

2 OSGi Management

• Make a web based management application

• What will we learn?– Create a servlet– Register a servlet with the Http Service– How to find out about the configuration of the

Framework– Start/Stop/Uninstall/Update bundles– Install bundles– Using XML, XSLT and HTML (a bit :-)

©1999-2003 aQute, All Rights Reserved

2 Management Agent

• Implemented as a servlet that generates XML with all the bundle information

<top> <error>message</error> <!-- optional --> <bundle id="…" location="…" name="…" state="…"> … description … </bundle></top>

• Accepts the following parameters:– action: start/stop/update/uninstall/install– uri:<uri for installing a bundle> (only present with

install)– bundleId: <id>

©1999-2003 aQute, All Rights Reserved

2 Management Agent

• Create a new project called "ma" (management agent)

• Add the osgi.jar and servlet.jar libraries (Properties:libraries)

©1999-2003 aQute, All Rights Reserved

2 Creating the Activator

• Copy the Activator from the previous exercise to the "ma" project– Notice the automatic package renaming!

• Modify the Activator:– The portal registration (but keep it, it is handy)– Remove the distributor related code

• Ignore the errors for the moment

©1999-2003 aQute, All Rights Reserved

2 Management Agent

• Copy the HttpTracker from the previous exercise• Modify the HttpTracker.addingService method,

we must register a servlet now:

public Object addingService( ServiceReference reference ) { HttpService http = (HttpService)super.addingService(reference); try { http.registerResources("/agent", "", this ); http.registerServlet("/agent/servlet", new AgentServlet(activator,context), null, this ); } catch( NamespaceException e ) { activator.log( "Name is already in use /agent", e ); } catch( Exception e ) { activator.log( "Unexpected exception ", e ); } return http;}

©1999-2003 aQute, All Rights Reserved

2 AgentServlet

• Create an AgentServlet class, it extends the HttpServlet class

BundleContextcontext;Activatoractivator;

AgentServlet( Activator activator, BundleContext context ) { this.context = context; this.activator = activator;}

©1999-2003 aQute, All Rights Reserved

2 AgentServlet

• The doGet method is called for an HTTP GET request:

public void doGet( HttpServletRequest rq, HttpServletResponse rsp ) throws IOException { String bundleId = rq.getParameter("bundle"); String action = rq.getParameter("action"); String uri = rq.getParameter("uri");// if install rsp.setContentType("text/xml");

PrintWriter pw = new PrintWriter( rsp.getWriter()); prolog(pw); pw.println( "<top>" ); doAction(bundleId, action, uri, pw); listBundles(pw); pw.println( "</top>" ); pw.close();}

©1999-2003 aQute, All Rights Reserved

2 AgentServlet

• List all the existing bundles as XML

public void listBundles(PrintWriter pw) { Bundle bundles[] = context.getBundles(); for ( int i=0; i<bundles.length; i++ ) { Bundle bundle = bundles[i]; Dictionary p = bundle.getHeaders(); String name = get(p,"Bundle-Name", "?" ); String description = get(p,"Bundle-Description", "?" ); pw.println( "<bundle" +" location='" + bundle.getLocation() + "'" +" name='" + name + "'" +" id='" + bundle.getBundleId() + "'" +" state='" + bundle.getState() + "'" +">"); pw.println( escape( description ) ); pw.println( "</bundle>"); }}

©1999-2003 aQute, All Rights Reserved

2 AgentServlet

• Perform the actual action indicated in the "action" parameter:

public void doAction(String bid,Stringaction,String uri,PrintWriter pw){ Bundle bundle = null; try { if (bid!= null ) bundle = context.getBundle( Long.parseLong(bid)); if ( action!= null ) { if ( action.equals("start") ) bundle.start(); else if ( action.equals("stop") ) bundle.stop(); else if ( action.equals("update") ) bundle.update(); else if ( action.equals("uninstall") ) bundle.uninstall(); else if ( action.equals("install") ) context.installBundle( uri ); }} catch( BundleException e ) { error(action, pw, bundle, e, e.getNestedException()); } catch( Exception e ) { error(action, pw, bundle, e, null );}}

©1999-2003 aQute, All Rights Reserved

2 AgentServlet

• Support methods:

public void error(String action, PrintWriter pw, Bundle bundle, Exception e, Throwable nested) { pw.println( "<error class='" + e.getClass().getName() + "' action='" + action+ "' bundle='" + bundle + "'>" ); pw.println( escape(e.getMessage()) ); pw.println( "</error>" );}public void prolog(PrintWriter pw) { pw.println("<?xml version='1.0' encoding='UTF-8'?>" ); pw.println( "<?xml-stylesheet type='text/xsl' title='Compact' href='agent.xsl'?>" );}String get( Dictionary p, String key, String dflt ) { String result = (String) p.get( key ); if ( result != null ) return result; return dflt; }

©1999-2003 aQute, All Rights Reserved

2 AgentServlet

• The escape() method is needed to prevent <&> from ending up in an attribute or text, confusing the XML parser.

String escape( String source ) { // Should escape the entities like <, >, & StringBuffer sb = new StringBuffer(); for ( int i=0; i<source.length(); i++ ) { char c = source.charAt(i); switch(c) { case '&': sb.append( "&amp;" ); break; case '<': sb.append( "&lt;" ); break; case '>': sb.append( "&gt;" ); break; default: sb.append( c ); }} return sb.toString(); }

©1999-2003 aQute, All Rights Reserved

2 XSL

• Notice the second line in the prolog:

<?xml-stylesheet type='text/xsl' title='Compact' href='agent.xsl'?>

• This is an instruction to the browser to use XML StyLe Transformation. XSL transforms the XML to HTML. This requires an XSL file called agent.xsl

• Copy this file from the CD (this is not an XSL course!)

• This page is served in our getResource in the HttpTracker

©1999-2003 aQute, All Rights Reserved

2 Management Agent

• Create the Manifest

• Create the JAR file (Export:Jar)

• Surf to http://localhost:8000/agent/servlet

• Or to http://localhost:8000/portal and select the management agent

• Simple isn't it?

©1999-2003 aQute, All Rights Reserved

2 What did we learn?

• We created a servlet that generates XML

• The XML was derived from the actual bundle configuration

• Servlet parameters were used to start/stop/install/uninstall/update bundles

• XSL was used to make XML

©1999-2003 aQute, All Rights Reserved

Conclusion

• Surprisingly little code is necessary to perform interesting functions

• Coupling to other parts is minimal because OSGi specified interfaces are intermediates

• Tools are available to simplify creation of manifest and bundle files

• This is only the beginning ...

©1999-2003 aQute, All Rights Reserved

Vendors With Tools & Courses

• Acunia - www.acunia.com

• aQute - www.aQute.se

• IBM - www.ibm.com/embedded

• Gatespace - www.gatespace.com

• ProSyst - www.prosyst.com

• Atinav - www.atinav.com

• Espial - www.espial.com

• See for more www.osgi.org

©1999-2003 aQute, All Rights Reserved

aQute

www.aQute.biz

+46 300 39800, Peter.Kriens@aQute.bi

z

top related