1. Motiváció
A hagyományos operációs rendszerek két
konstrukcióval biztosítják a kóddarabok
igényeknek megfelelő elválasztását ill.
mások által való
hozzáférését.
- A végrehajtható állomány
indításakor keletkező processz el van választva
más processzektől, egyéb rendelkezés
híján más processzek nem hívhatnak meg
függvényeket a processzben. Az operációs
rendszer tehát szeparációt
biztosít.
- Lehetőség van megosztott könyvtárak
használatára, melyek egyszer töltődnek a rendszerbe
és minden processz használhatja őket (Shared Object,
Dynamic Link Library).
Több erőfeszítés volt, hogy a Jáva
tetején (egy logikai virtuális gépben) az
operációs rendszerek szolgáltatásaihoz
hasonló funkcionalitást hozzanak létre. Ezek
közül a leginkább elfogadott megoldás az Open
Service Gateway Initiative (OSGi). A legfrissebb OSGi
specifikáció az R3 (Revision 3), az OSGi Alliance
oldaláról (
http://www.osgi.org)
letölthető.
Az OSGi-t eredetileg u.n. home gateway-ek számára
fejlesztették ki. A home gateway egy doboz, ami kapcsolatban
áll egy szolgáltatóval és a
felhasználó által előfizetett
szolgáltatásokhoz ad elérést. Pl.
lehetséges, hogy a home gateway a
kábelszolgáltatóhoz tartozik és
filmkölcsönzési (pay per view)
szolgáltatásokhoz ad hozzáférést.
Ekkor a gateway-en futó program lehetővé teszi filmek
kiválasztását, majd a kiválasztott filmet
letölti és számláz. A gateway-t tehát
a szolgáltató menedzseli, ő tölti fel szoftverrel
és tartalommal, a felhasználó csupán
használja az általa nyújtott
szolgáltatásokat. Ezen környezet
követelményei miatt az OSGi elsőrangú
menedzselhetőségi lehetőségeket nyújt, jobbakat,
mint bármely más Jáva alkalmazásmodell. Az
OSGi-t mostanában bővítik ki
végfelhasználói rendszerekben (pl. Eclipse)
való használatra.
2. Batyu (bundle)
Az OSGi alapegysége a batyu (bundle). A batyu
különös keveréke a csomagolási
formátumnak és a végrehajtási
egységnek.
- A batyu csomagolási formátumot definiál. Az
OSGi keretrendszer batyunként telepítí a
programegységeket. A batyu Jáva kódot, statikus
erőforrásokat (pl. képek) és
különböző információkat tartalmazó
leírófájlt (manifest, ld. később) tartalmaz.
- A batyu Jáva kódot exportálhat és
importálhat, ezt Jáva csomagonként (package)
teszi. Ezzel megvalósítja a megosztott
könyvtár funkcionalitását.
- A batyu futási egységként
funkcionálhat, ez nem kötelező. Ha a batyu
futatható, akkor a batyut el lehet indítani és le
lehet állítani.
- A batyuhoz jogok köthetők, ha a JVM támogatja a
Jáva biztonsági rendszert. Ekkor batyunként
előírható, melyik batyu milyen jogosultágot kap.
- A batyu életciklusának változásai
eseményeket generálnak, amikre más batyuk
feliratkozhatnak és követhetik őket.
- A batyu service-eket regisztrálhat, amelyeken
keresztül más batyuk az egyszerű Jáva
metódushívásnál gazdagabb módon
érhetik el. A service elválasztja egymástól
az interfészt és az implementációt, pl.
különböző XML elemzők regisztrálhatnak XML elemző
service-eket és a service tulajdonságai alapján
lehet kiválasztani a megfelelő service-t, majd a
kiválasztás alapján meghívni a
szolgáltatást.
A batyu egy JAR fájl. A batyuban alapvetően Jáva
osztályok, a Jáva osztályokból elért
statikus erőforrások (pl. képek) és a Jáva
osztályokból elért natív kóddarabok
lehetnek. A batyuban levő dolgok értelmezéséhez az
immár megszokott módon leíró kell, ez a
batyu esetén a szabványos manifest fájlban
(META-INF/MANIFEST.MF) van. Íme egy példa egy OSGi
manifest fájlra:
Bundle-Name:
Helloworld
Bundle-Version:
1.1
Bundle-Description:
Hello, world
Bundle-Vendor:
FreeWare
Bundle-Copyright:
'Copyleft (c) 1999-2002.'
Bundle-Activator:
example.osg.HelloWorld.HelloWorld_Activator
Import-Package:
org.osgi.service.cm
Export-Package:
example.osg.exported_package
A Bundle-Name-től a Bundle-Copyright-ig terjedő fejlécek a
batyuról tárolnak információkat. A
Bundle-Activator annak az osztálynak a neve, amelyiknek
metódusai meghívódnak a batyu
elindítása és leállítása
esetén. Ez opcionális, mint látni fogjuk, egy
batyu lehet úgy is igen hasznos, hogy nem
elindítható. A batyu aktivizáló
osztályára lássunk egy példát!
public class
HelloWorld_Activator implements org.osgi.framework.BundleActivator {
public void start(BundleContext bc) {
...
}
public void stop( BundleContext bc ) {
...
}
}
A batyu elindításakor a batyu aktivizáló
osztályát példányosítja az OSGi
keretrendszer, majd meghívja a start() metódust. A
metódus megkap egy BundleContext egyedre mutató
referenciát. A BundleContext metódusain keresztül
- A keretrendszer eseményeire lehet feliratkozni
- Service-eket lehet regisztrálni (ld. később)
- Service-ekhez lehet hozzáférni
- Új batyukat lehet installálni
- A már installált batyukat le lehet kérdezni
ill. hozzájuk lehet férni
- A batyu saját Bundle objektumát meg lehet szerezni.
A Bundle objektumon keresztül a batyut el lehet indítani/le
lehet állítani, az állapotát le lehet
kérdezni, a verzióját frissíteni lehet vagy
el lehet távolítani.
- Hozzá lehet férni a batyuhoz rendelt saját
könyvtárhoz a fájlrendszeren. Itt lehet a batyu
által írt/olvasott fájlokat tárolni.
3. Export és Import
Az OSGi környezet egész sajátos tulajdonsága
az export-import mechanizmus. Ennek segítségével a
batyu kiajánlhatja a benne levő osztályokat a többi
batyunak. A kiajánlás egysége a Jáva
package. Tehát a batyu pl. kiajánlhatja a
com.mycomp.superfeature.* osztályokat más batyuknak. A
batyu nem kiajánlott osztályai direktben nem lesznek
elérhetők a z importáló batyu
részére, de persze a kiajánlott csomag
elérhetővé teheti őket, pl. a kiajánlott csomag
egy osztályának egy metódusa visszaadhat
referenciát nem kiajánlott osztály egyedére.
A kiajánlást a manifest fájlban kell
deklaráljuk:
Export-Package:
com.mycomp.superfeature
Opcionálisan deklarálhatja a csomag
verzióját is:
Export-Package:
com.mycomp.superfeature; specification-version="2.1"
Az importáló batyunak is deklarálnia kell, hogy
bizonyos osztályokat nem maga tartalmaz, hanem importál:
Import-Package:
com.mycomp.superfeature
Ugyancsak van
lehetőség a csomag verzió megadására.
Import-Package:
com.mycomp.superfeature; specification-version="1.5"
Ez azt jelenti, hogy a csomagot csak olyan kiajánló
batyutól szabad importálni, aki a megadott
verziójú, vagy magasabb verziójú csomagot
ajánlott ki. A példánk tehát elfogadja majd
az előző (2.1-es) kiajánlott csomagot, mert az magasabb az
általunk igényelt (1.5-ös) verziónál.
Amikor az OSGi keretrendszer a batyut installálja,
végrehajtja a kiajánlások és importok
feloldását. A feloldás során a Jáva
osztálybetöltő mechanizmusát használja
kreatívan. Minden batyuhoz saját
osztálybetöltőt készít, így a batyuk
egymás osztályait alaphelyzetben nem
látják. Ha azonban egy batyu importál egy
csomagot, akkor az importáló batyu
osztálybetöltője ezen csomagba tartozó
osztályok betöltését az
exportáló batyu osztálybetöltőjének
delegálja. Ezt úgy teszi, hogy referenciát tart a
kiajánló batyu csomagbetöltőjére. Az
export-import mechanizmus miatt a batyuk között
függőségek jönnek létre, amiket az OSGi
keretrendszer nyilvántart. Az a batyu, amelynek
függőségei rendben vannak, feloldott állapotban van.
Ez azt jelenti, hogy minden importált csomagját ki lehet
elégíteni a rendszeren installált batyuk
kiajánlott csomagjaiból. Ha valamelyik
importhoz tartozó csomag hiányzik (nem exportálja
semmilyen más batyu), akkor az importáló batyu
nem feloldott állapotban
van. Nem feloldott batyut nem lehet használni, pl. nem lehet
elindítani, nem lehet importálni tőle, stb.
3. A batyu állapotai
Az export-import mechanizmussal felvértezve immár
górcső alá vehetjük a batyu állapotait.
- Installált (installed). Ez azt jelenti, hogy a batyut
sikeresen installálta z OSGi keretrendszer, a batyu
formátuma rendben levőnek találtatott.
- Feloldott (resolved). Ez azt jelenti, hogy a batyu export-import
függőségeit sikeresen kielégítették. A
batyu kiajánlott csomagjai használhatók.
- Indulás közben (starting). Ez azt jelenti, hogy a
batyut elindították, de a start() metódusa
még nem tért vissza.
- Aktív (active). A start() metódus
visszatért, a batyu fut.
- Leállás közben (stopping). A batyu stop()
metódusát meghívták, de még nem
tért vissza. Ha a stop() visszatér, a batyu újra
feloldott állapotba kerül.
- Eltávolítva (uninstalled). A batyut
eltávolították a rendszerből, többé
nem használható.
4. Szolgáltatások (service)
Az export-import mechanizmus mellett az OSGi másik
sajátossága a szolgáltatás (service)
architektúra. A batyuk objektumokat regisztrálhatnak
név alatt a szolgáltatáskatalógusban
(service registry). A regisztrált objektum egy
szolgáltatás interfészt kell implementáljon
és az objektum ezen interfész nevén kell
regisztrálva legyen. Ezt legegyszerűbb egy példán
át megvizsgálni.
A következő a szolgáltatás interfész
kódja:
public interface
ServiceIf {
public
String message();
public
void setMessage( String message );
}
A szolgáltatás objektum implementálja ezt az
interfészt:
public class
ServiceObject implements ServiceIf {
public
String message() {
...
}
public
void setMessage( String message ) {
...
}
}
A batyu regisztrálja a szolgáltatást (tipikusan a
start() metódusban)
void start(
BundleContext bc ) {
...
serviceObject = new ServiceObject();
serviceDictionary = (Dictionary)new Hashtable();
myServiceRegistration = bc.registerService(
ServiceIf.class.getName(), //
szolgáltatásinterfész neve
(Object)serviceObject, // maga a
szolgáltatásobjektum
serviceDictionary ); // a szolgáltatás
tulajdonságai (most üres)
...
}
A szolgáltatást ki kell regisztrálni a
katalógusból, ha már nem elérhető
(tipikusan a stop() metódusban).
myServiceRegistration.unregister();
Ha valaki szolgáltatást akar használni, ismernie
kell a szolgáltatásinterfész nevét. Ennek
alapján a BundleContext két metódusával
megszerezhető a szolgáltatás objektuma, amin aztán
a szolgáltatás metódusai meghívhatók.
BundleContext
bc; // Elmenthető pl. a start
metódusban
ServiceReference
sr = bc.getServiceReference( ServiceIf.class.getName()
);
ServiceIf so
= (ServiceIf)bc.getService( sr );
String s =
so.message(); //
Szolgáltatás hívása az
interfészén keresztül
A szolgáltatások megfelelő használatához a
batyuknak helyesen kell viselkedniük, különben az OSGi
keretrendszer nem tud megfelelően működni. Ha egy batyu
referenciát tárol egy másik batyu
osztálybetöltője által definiált objektumra,
az objektumhoz tartozó osztályt (és annak
összes függő osztályát) az Jáva
szemétgyűjtője nem tudja eltakarítani, ha a
kérdéses batyut eltávolítják vagy
újabb verziót installálnak. Ennek megfelelően a
batyuknak figyelniük kell az általuk használt
szolgáltatásokhoz tartozó batyuk
életcikluseseményeire és eldobniuk minden
referenciát, ha a batyut eltávolítják vagy
frissítik.
5. Jáva biztonság és OSGi keretrendszer
A Jáva 2-es változata egy teljesen
megújított biztonsági keretrendszert tartalmaz,
ami a korábbi "homokozó" modellel gyökeres
szakítást jelent. Ebben a modellben a védelmi
kontextusokhoz jogosultsági (Permission) objektumokat rendelnek.
A Jáva futtatórendszer nyilvántartja az
aktív védelmi kontektusokat és ezen kontextusokhoz
rendelt jogosultságok metszetét képezi. Ez az
aktív jogosultságkészlet. A védendő
kód az érzékeny műveletsorozat
végrehajtása előtt ellenőrzi, az aktív
jogosultságkészletben van-e olyan jogosultság,
amelyik a művelethez szükséges jogosultágot
implikálja. (Pontos egyezés nem szükséges,
pl. FilePermission( "read,write", "<<ALL FILES>>" )
implikálja a FilePermission( "read", "myfile.txt")
jogosultságot vagy pl. AllPermission implikál
bármilyen jogosultságot). A biztonsági
keretrendszer alapértelmezett implementációja a
védelmi kontextusokat a Jáva kódbázishoz
rendeli, pl. meg lehet adni a file://javalibs/speclib.jar
kódbázishoz tartozó jogosultságokat. A
Jáva futtatórendszer nyilvántartja, milyen
kódbázisokon - védelmi zónákon -
haladt át a hívás és az aktív
jogosultságkészlet a hívás által
végigjárt összes kódbázis
jogosultságainak metszete.
Az OSGi keretrendszerre a jogosultsági rendszer
kétféleképpen hat. Egyfelől a keretrendszer
definiálja, milyen jogosultságok kellenek bizonyos
szolgáltatások
igénybevételéhez. Pl. PackagePermission(
"com.mypackage", "EXPORT" ) megengedi a batyunak, hogy a com.mypackage
Jáva package-t exportálja. Egy másik példa:
ServicePermission( "com.myservice", "GET") megengedi a batyunak, hogy
megszerezze a com.myservice szolgáltatás interfész
névvel regisztrált szolgáltatás
szolgáltatásobjektumát. A paraméterek
nélküli AdminPermission megengedi a batyunak, hogy
meghívjon OSGi keretrendszer menedzsmentfunkcionalitást,
pl. installáljon egy batyut.
Másfelől batyunként lehet beállítani a
jogosultságokat, tehát nem kell a
kódbázissal bíbelődni. Ez a Permission Admin
szolgáltatás feladata. A Permission Admin
segítségével lekérdezhetők és
módosíthatók a batyuk jogosultságai.
Módosításhoz persze AdminPermission kell.
6. Fontosabb OSGi szolgáltatások
Az OSGi egy tucatnyi szolgáltatást definiál.
Ezeknek többsége opcionális. Az alábbiakban
lássunk néhányat a fontosabbakból.
- A Package Admin segítségével
lekérdezhetjük a batyuk export-import függőségi
listáját
- A Log Service elérhetővé teszi a keretrendszer
közös naplóját
- A Configuration Admin segítségével minden
batyuhoz konfigurációs paraméterek
gyűjteménye rendelhető. Ezeknek
változásairól a batyu visszajelzést kap
(pl. ha az adminisztrátor távolról
megváltoztatja a konfigurációt, a batyu
hívást kap)
- A Http Service lehetővé teszi, hogy szervleteket/JSP-ket
batyuba csomagoljunk és a batyu installálása
után a webalkalmazás regisztrálódjon
- Az User Admin szolgáltatás lehetővé teszi
felhasználó autentikációs modulok
dugaszolását a rendszerbe és az
autentikáció után a felhasználó
jogosultságainak megszerzését
(autorizáció). Ez a szolgáltatás nem
Jáva permission-ökön alapul.