Pokrocile aspekty komponentovych technologii

Transkript

Pokrocile aspekty komponentovych technologii
Západočeská univerzita v Plzni
Fakulta aplikovaných věd
Katedra informatiky a výpočetní techniky
Diplomová práce
Pokročilé aspekty komponentových
modelů
Plzeň, 2009
Vojtěch Liška
Orig. zadání
1
Prohlašuji, že jsem diplomovou práci vypracoval samostatně a výhradně s použitím citovaných
pramenů.
V Plzni dne 18. května 2009
Vojtěch Liška
2
Abstrakt
Disciplína softwarového inženýrství založeného na komponentách je přístup, ve kterém
jsou systémy stavěny z již dříve existujících softwarových komponent. Takto složené systémy mohou být charakterizovány jejich funkcionalitou, ale také jejich mimofunkčními
charakteristikami.
Cílem této diplomové práce je navrhnout a implementovat rozšíření existujícího experimentálního komponentového modelu CoSi o pokročilé aspekty komponentových
technologií - mimofunkční charakteristiky a balíky komponent.
V první části se práce zabývá obecnými principy komponentových technologií, popisem vlastností komponent, příklady komponentových modelů a problematikou popisu
mimofunkčních charakteristik komponent.
Druhá část práce se věnuje návrhu, specifikaci a implementaci rozšíření komponentového modelu CoSi o mimofunkční charakteristiky a balíky komponent.
Abstract
Component-based software engineering is an approach where systems are built from
preexisting software components. These systems are described by their functionality,
but also by their non-functional characteristics.
The goal of this thesis is to desing and implement an extension of the CoSi component model that covers advanced aspects of the component models - extra-functional
properties and component packages.
In the first part of the thesis we describe the basic component technology principles.
We also describe components and their specification, present several existing component
models and discuss extra-functional properties specification.
The second part of the thesis describes the design, specification and implementation
of the mentioned CoSi component model extension.
3
Obsah
1 Úvod
7
2 Obecně o komponentových technologiích
8
2.1
Úvod do komponentových technologií . . . . . . . . . . . . . . . . . . . . . . .
2.2
Základní principy komponentových technologií
8
. . . . . . . . . . . . . . . . .
11
2.2.1
Komponenty . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
11
2.2.2
Rozhraní komponenty . . . . . . . . . . . . . . . . . . . . . . . . . . .
12
2.2.3
Kontrakty . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
13
2.2.4
Příklad komponentového systému . . . . . . . . . . . . . . . . . . . . .
14
3 Komponentové modely
16
3.1
O komponentových modelech . . . . . . . . . . . . . . . . . . . . . . . . . . .
16
3.2
EJB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
17
3.3
OSGi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
18
3.3.1
OSGi Service Platform . . . . . . . . . . . . . . . . . . . . . . . . . . .
19
SaveCCM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
22
3.4.1
Úvod . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
22
3.4.2
Architektonické elementy . . . . . . . . . . . . . . . . . . . . . . . . .
23
3.4
3.5
PicoContainer
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4 Specifikace mimofunkčních charakteristik
25
27
4.1
Definice EFP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
27
4.2
Přístupy k EFP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
27
4.2.1
NoFun
28
4.2.2
Component Quality Model
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . .
5 CoSi - návrh rozšíření komponentového modelu
5.1
28
31
Obecně o CoSi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
32
5.1.1
Meta-model CoSi
. . . . . . . . . . . . . . . . . . . . . . . . . . . . .
32
5.1.2
Obsah komponenty
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
33
4
Obsah
5.2
Mimofunkční charakteristiky . . . . . . . . . . . . . . . . . . . . . . . . . . . .
34
5.2.1
Obecné principy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
35
5.2.2
Definice EFP
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
35
5.2.3
Registr EFP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
36
5.2.4
Popis EFP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
36
5.2.5
Porovnávání EFP
. . . . . . . . . . . . . . . . . . . . . . . . . . . . .
37
5.3
Balíky komponent . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
37
5.4
Další rozšíření modelu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
38
5.4.1
Poskytované a vyžadované balíky Java tříd
. . . . . . . . . . . . . . .
38
5.4.2
Dependency injection . . . . . . . . . . . . . . . . . . . . . . . . . . .
39
6 Specifikace CoSi
6.1
41
Komponentový model CoSi . . . . . . . . . . . . . . . . . . . . . . . . . . . .
41
6.1.1
Obsah komponenty - podrobněji
. . . . . . . . . . . . . . . . . . . . .
42
6.1.2
Specifikace komponenty - soubor manifest.mf . . . . . . . . . . . . . .
45
6.1.3
Registr mimofunkčních charakteristik
. . . . . . . . . . . . . . . . . .
50
6.1.4
Distribuční forma komponenty . . . . . . . . . . . . . . . . . . . . . .
51
6.1.5
Balík komponent
. . . . . . . . . . . . . . . . . . . . . . . . . . . . .
52
6.1.6
Specifikace balíku komponent - soubor manifest.mf . . . . . . . . . . .
52
6.1.7
Distribuční forma balíku komponent . . . . . . . . . . . . . . . . . . .
54
Životní cyklus komponenty a balíku komponent . . . . . . . . . . . . . . . . .
55
6.2.1
Proces vyhodnocení komponenty . . . . . . . . . . . . . . . . . . . . .
57
6.2.2
Rozhraní komponenty a balíku komponent . . . . . . . . . . . . . . . .
59
Kontejner . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
61
6.3.1
Rozhraní kontejneru . . . . . . . . . . . . . . . . . . . . . . . . . . . .
62
6.3.2
Základní služby kontejneru . . . . . . . . . . . . . . . . . . . . . . . .
63
6.4
Class loading architektura . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
66
6.5
Rozdíly proti ostatním specifikacím . . . . . . . . . . . . . . . . . . . . . . . .
67
6.2
6.3
7 Implementace změn
7.1
7.2
7.3
69
Jádro kontejneru . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
69
7.1.1
Architektura jádra kontejneru . . . . . . . . . . . . . . . . . . . . . . .
69
Implementace služeb . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
73
7.2.1
Služba ExtrafuncRegistryService . . . . . . . . . . . . . . . . . . . . .
73
7.2.2
Služba SimpleShell . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
73
Ukázkové scénáře . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
75
7.3.1
Ukázkový scénář - meteorologická stanice . . . . . . . . . . . . . . . .
75
7.3.2
Ukázkový scénář - SaveCCM/CoSi transformace . . . . . . . . . . . . .
76
5
Obsah
8 Závěr
80
Seznam zkratek
81
Literatura
82
Přílohy
i
6
1 Úvod
Během posledních deseti let se komponentové technologie přesunuly z oblasti čistě
vědeckého výzkumu do praxe a staly se součástí konstrukce moderních softwarových
systémů. Softwarový průmysl tak převzal myšlenku běžnou v jiných oborech – skládání
složitých systému z jednodušších a menších již dříve existujících funkčních celků –
komponent. Proces skládání komponent umožňuje rychlejší konstrukci výsledného systému a snížení celkových nákladů. Takto složené systémy mohou být charakterizovány
jejich funkcionalitou (co systém dělá) a jejich mimofunkčními charakteristikami (jak se
systém chová s ohledem na pozorovatelné vlastnosti jako je výkon, spolehlivost, atd.).
Tyto charakteristiky jsou často opomíjeny, ačkoliv mohou mít vážný dopad na důležitá
rozhodnutí v oblasti architektury a návrhu systému.
Následující text nejprve seznámí s obecnými principy komponentových technologií
(kapitola 2), tedy tím, co jsou to komponenty, k čemu slouží a jakou hrají roli v procesu
vytváření softwarových celků založených na komponentách. Navazující kapitola („Komponentové modely“) uvede do problematiky komponentových modelů a krátce představí
několik jejich existujících zástupců. Teoretická část diplomové práce je zakončena kapitolou 4, která se blíže věnuje existujícímu výzkumu v oblasti popisu mimofunkčních
charakteristik komponent.
Cílem práce je analyzovat, kriticky zhodnotit existující implementaci komponentového modelu CoSi a navrhnout rozšíření modelu o pokročilé aspekty komponentových
technologií – mimofunkční charakteristiky a balíky komponent. Praktickou část práce
tedy tvoří návrh rozšíření modelu o tyto pokročilé aspekty (kapitola 5), specifikace
upraveného komponentového modelu (kapitola 6) a v neposlední řadě implementace navržených změn do existující implementace CoSi (kapitola 7) a ověření jejich funkčnosti
na ukázkových příkladech.
7
2 Obecně o komponentových
technologiích
Tato kapitola pojednává o komponentových technologiích a o softwarové disciplíně,
která se komponentovými technologiemi zabývá - softwarovém inženýrství založeném
na komponentách (dále jen CBSE1 ). Kapitola z velké části čerpá z článku [3] a úvodních kapitol knihy [8]. Kniha se zabývá tvorbou spolehlivých systémů založených na
komponentách a je velmi dobrým úvodem do komponentových technologií.
2.1 Úvod do komponentových technologií
V posledních několika desetiletích jsme svědky rozmachu informačních technologií a
použití software v průmyslu, obchodu, správě, výzkumu a v každodenním životě. Software už není používán jen okrajově v čistě technických systémech. Místo toho se stává
nejdůležitějším faktorem v mnoha odvětvích trhu. Tento trend zvyšuje požadavky na
softwarové produkty, zejména požadavky jako je robustnost, spolehlivost, použitelnost,
přizpůsobitelnost spolu s jednoduchou instalací a nasazením do provozu. Výsledkem
toho je stále se zvyšující velikost a složitost softwarových produktů. Hlavní výzvou
dnešních softwarových vývojářů je poradit si s touto složitostí a umět se rychle přizpůsobit změnám.
V tradičním pojetí byl software vyvíjen se zaměřením na dodání a vývoj jednoho
konkrétního systému a na to, jak je dodržen rozpočet na vývoj a konečný termín dodání.
Při tom se nemyslelo na další uplatnění vyvinutého software a na vyhlídky na jeho
evoluci. Tento přístup často vedl ke zvýšeným nákladům na provoz a údržbu systému a
k nesplnění požadavků na kvalitu systému.
Z těchto problémů vzešla základní myšlenka o znovupoužitelnosti software. Jeden
z přístupů, který tuto myšlenku vzal za svou, je vývoj založený na komponentách (dále
1 Component
based software engineering
8
Úvod do komponentových technologií
Obrázek 2.1: Návrhový vzor založený na komponentách (převzato z [3])
jen CBD), kde systémy vyvíjíme skládáním již hotových komponent místo psaní systémů
od začátku.
Systémy založené na komponentách jsou výsledkem přijmutí strategie návrhu založené na komponentách. Termínem strategie návrhu je myšleno něco velmi podobného
k vysokoúrovňovému návrhovému vzoru, který je popsaný typy komponent v systému
a vzory jejich interakce [4]. Technologie softwarových komponent zahrnuje koncepty,
které podporují a odráží tento návrhový vzor (viz obrázek 2.1)
CBD vyžaduje systematický přístup pracující s výhodami softwarových kompoent a
zároveň snižující rizika jejich použití na minimum. Tento přístup popisuje disciplína
CBSE. CBSE je oblast softwarového inženýrství zaměřená na vývoj softwarových komponent a systémů zkonstruovaných z těchto komponent. Poskytuje metody a nástroje na
podporu různých aspektů CBD2 .
Komponenta (v obrázku 2.1 pod číslem 1) v CBD je softwarová implementace, která
může být spuštěna na fyzickém či logickém zařízení [3]. Komponenta implementuje
jedno nebo více rozhraní (2). Tato rozhraní jsou s komponentou pevně spjata a popi2V
některých případech jsou pojmy CBD a CBSE používány jako synonyma. V této diplomové práci je
CBSE použito ve smyslu systematického a disciplinovaného přístupu k CBD.
9
Úvod do komponentových technologií
sují component obligations3 , které jsou často popisovány jako kontrakty (3). Kontrakty
zaručují, že se komponenty vyvinuté nezávisle na sobě řídí určitými pravidly. Mohou
spolu interagovat a výsledek této interakce je předvídatelný. Kontrakty také zaručují,
že komponenty je možné nasadit (deploy) (4) do standardních sestavovacích (build-time
environment) a běhových prostředí (run-time environment).
Systém založený na komponentách je založený na malém počtu odlišných typů komponent. Každý z těchto typů zastává specializovanou roli v systému (5) a je popsaný
rozhraním. Množina typů, jejich rozhraní a specifikace povolených vzorů interakce mezi
typy komponent dohromady tvoří komponentový model (6). Komponentový framework
(7) pak poskytuje různorodé služby pro podporu a vynucení komponentového modelu.
Komponentové frameworky jsou v mnoha ohledech podobné specializovaným operačním
systémům, přestože operují na mnohem vyšších úrovních abstrakce.
CBD přináší mnoho výhod do vývoje software. Jsou to například:
∙ nezávislá rozšíření
∙ snížený čas na dodání systému na trh
∙ efektivnější kontrola nad rozsahem systému, která vede ke snazšímu vývoji a
údržbě systému
∙ znovupoužitelnost komponent v dalších systémech
CBD ale nepřináší jen výhody. Jsou zde i nevýhody a rizika, která mohou ohrozit úspěch
nasazení tohoto přístupu [8]:
∙ Není vždy zřejmé, co je možné použít znovu a co ne. Požadavky na komponenty
nejsou vždy známé předem a jsou často nepřesně nebo nedostatečně definovány.
∙ Vývoj znovupoužitelných komponent klade zvýšené nároky na čas a peníze.
∙ Pro splnění podmínky znovupoužitelnosti musí být komponenty dostatečně obecné,
rozšiřitelné a přizpůsobitelné, což může vést ke komplikovanější použitelnosti a
zvýšeným nárokům na výpočetní výkon.
∙ Údržba komponent může být velmi drahá, protože komponenty musí reagovat na
různé požadavky od různých aplikací z různých prostředí a s různými požadavky
na spolehlivost.
3 závazky
nebo také povinnosti komponenty
10
Základní principy komponentových technologií
2.2 Základní principy komponentových technologií
Základním principem CBSE je koncept komponenty. Další termíny jako rozhraní, kontrakt nebo framework jsou úzce spjaty s CBSE právě přes koncept komponenty. Tato
sekce dává přehled o konceptu komponenty v CBSE. Druhá část této sekce popisuje
koncept rozhraní a kontraktů a diskutuje problematiku těchto konceptů a jejich vzájemné
vztahy.
2.2.1 Komponenty
Protože komponenty jsou srdcem komponentových technologií, potřebujeme přesně definovat, co to je komponenta, abychom mohli porozumět základním principům komponentových technologií. Ačkoliv koncept a myšlenka komponent jako menších funkčních
celků, ze kterých se skládá systém, by se mohla zdát jasná a intuitivní, neexistuje jednoznačná všeobecně přijímaná definice komponenty. Szyperski [19] definuje komponentu
výčtem charakteristických vlastností komponenty:
A software component is a unit of composition with contractually specified
interfaces and context dependencies only. A software component can be
deployed independently and is subject to composition by third parties.
Aby mohla být komponenta nezávisle nasazena, je nutné jasné odlišení komponenty od
jejího prostředí a od ostatních komponent. Komponenty lze skládat a komunikují s prostředím a ostatními komponentami přes rozhraní podléhající kontraktu. Tato rozhraní
jsou jasně definována a jejich implementace je zapouzdřena v komponentě a není přímo
přístupná z prostředí komponenty. To dělá z komponenty jednotku nezávislého nasazení.
Motivace pro nezávislé nasazení je zřejmá – použití komponenty by nemělo záviset na
informacích a nástrojích, které má pouze poskytovatel komponenty. Pokud je to splněno,
je možné, aby se systém skládal z komponent z různých nezávislých zdrojů.
Crnkovič [8] se zabývá i dalšími definicemi komponent a snaží se najít společný jmenovatel pro komponenty. Aby bylo možné úplně popsat a zajistit její korektní integraci,
správu a aktualizaci, měla by se podle něj komponenta skládat z následujících elementů:
∙ Množiny rozhraní poskytovaných prostředím nebo požadovaných od prostředí.
∙ Vykonatelného kódu, který může být spřažený s kódem jiných komponent přes
rozhraní.
11
Základní principy komponentových technologií
Dále uvádí, že pro zlepšení kvality komponenty by měla specifikace komponenty obsahovat následující elementy:
∙ Specifikaci vyžadovaných nebo poskytovaných mimofunkčních charakteristik (dále
jen EFP - extra-functional properties4 ).
∙ Validační kód potvrzující navrhované propojení s jinou komponentou.
∙ Dodatečné informace jako např. informace o designu, dokumenty související se
splněním specifikací požadavků na komponentu nebo příklady použití.
2.2.2 Rozhraní komponenty
Rozhraní jsou přístupové body ke komponentám. Definují způsoby, jakými se mohou
klienti komponenty napojit na služby poskytované komponentou. Pokud komponenta
poskytuje více služeb, které odpovídají více přístupovým bodům ke komponentě, měla
by mít i více rozhraní.
Je důležité upozornit na to, že rozhraní sama o sobě neposkytují žádnou implementaci.
Pouze vyjmenovávají seznam operací, které může komponenta vykonávat. Jak bylo již
napsáno výše, je důležité striktně oddělovat rozhraní od implementace. Toto oddělení
zajišťuje, že [8]:
1. implementace komponenty může být změněna bez zásahu do rozhraní, takže se
nemusí systém, ve kterém je komponenta nasazena, znovu sestavovat
2. nová rozhraní a implementace mohou být přidávána bez zásahu do stávajících
rozhraní komponenty, což zajistí lepší přizpůsobivost
Identifikujeme dva typy rozhraní (viz obrázek 2.2 na následující straně; šipka označuje
směr volání mezi komponentami):
1. poskytovaná (exported/provided interface) - představuje služby, které komponenta
poskytuje prostředí
2. vyžadovaná (imported/required interface) - definuje, jaké služby komponenta vyžaduje od prostředí
4 Tyto
charakteristiky jsou také známé jako kvalitativní charakteristiky (quality attributes). Je to např.
výkon, spolehlivost, přesnost, bezpečnost, atd.
12
Základní principy komponentových technologií
Obrázek 2.2: Rozhraní komponenty
Specifikace rozhraní v současných technologiích mají vážné nedostatky. Jedním z těchto
nedostatků je zaměření jazyků popisujících rozhraní5 na syntaktickou stránku popisu
rozhraní jako např. vstupy a výstupy, která ale neříká nic o sémantice operací (tzn.
o tom, co komponenta opravdu dělá). Rozhraní také neumožňují uvádět kontextové závislosti komponent. Další nevýhodou je to, že rozhraními můžeme popsat pouze funkční
charakteristiky komponent, ale už ne EFP. Tyto nevýhody se snaží řešit nástroj, který
má za cíl přesně specifikovat chování komponent.
2.2.3 Kontrakty
Kontrakty poskytují přesnější specifikaci chování komponenty. Ačkoliv by se mohlo zdát,
že rozhraní a kontrakty jsou velmi podobné, jedná se o rozdílné koncepty. Na rozdíl od
rozhraní, které popisuje operace komponent, kontrakty specifikují chování komponent a
interakci mezi různými komponentami.
Podle Meyera [18] kontrakt specifikuje seznam globálních neměnných vlastností spravovaných komponentou (invariant). Pro každou operaci komponenty pak obsahuje seznam podmínek, které musí klient splnit (precondition) a seznam podmínek, které se
komponenta zavazuje splnit (postcondition). Komponenta pak může spoléhat na to, že
všechny preconditions jsou splněny před zavoláním její operace. Před návratem z operace musí komponenta splnit to, k čemu se zavázala a klient na to může spoléhat.
Kontrakty je ale možné chápat šíře. V takovém případě kromě specifikace chování
jedné komponenty umožňují specifikovat vzájemné chování mezi skupinou komponent.
V této souvislosti uvádějí autoři [8]:
∙ participující komponenty,
∙ roli každé z participujících komponent,
∙ invariant,
5 např.
IDL - interface definition language
13
Základní principy komponentových technologií
∙ specifikaci metod, které vytvářejí instanci kontraktu.
Hierarchicky je možné kontrakty rozčlenit do čtyř úrovní [5]:
1. Syntaktická úroveň. Specifikuje operace, které může komponenta vykonávat spolu
s vstupně/výstupními parametry, které komponenta vyžaduje.
2. Úroveň týkající se chování. Specifikuje předchozí a následné podmínky pro operace.
3. Synchronizační úroveň. Specifikuje synchronizaci mezi různými službami a voláními metod.
4. Úroveň kvality služeb (QoS - Quality of Service). Specifikuje EFP.
2.2.4 Příklad komponentového systému
Abychom ukázali výhody komponentových technologií obsahuje tato sekce příklad komponentového systému. Jedná se o jednoduchou hypotetickou meteorologickou stanici.
Stanice se skládá z několika spolupracujících komponent (viz obrázek 2.3):
∙ Senzory (WindspeedSensor, TemperatureSensor) - komponenty, které mají za úkol
dodávat v pravidelných intervalech data (například o teplotě, tlaku, rychlosti větru
nebo vlhkosti).
∙ Registr senzorů (SensorRegistry) - komponenta, která má za úkol vést evidenci
všech senzorů v systému. Senzory se do komponenty registrují.
∙ Měřící stanice (MeasuringStation) - komponenta, která pracuje s daty ze senzorů
a zpracovává je (například je může zobrazovat nebo dělat statistickou analýzu dat).
Komponenta používá registr senzorů pro získání těchto dat.
Výhody komponentového přístupu v tomto příkladu jsou zřejmé. Měřící stanice se nestará o to, jaké senzory má k dispozici. Pouze se podívá do registru senzorů (použije
službu z rozhraní registru), vybere si některé (nebo všechny) a zpracuje jejich data.
Registr nemusí vědět vůbec nic o měřicí stanici ani o senzorech, které uchovává. Pouze
poskytuje služby, které umožní senzorům se zaregistrovat. Stejně tak senzory (může
jich být libovolné množství) nemusí vědět vůbec nic o tom, co se bude dít s jejich
daty, pouze musí data poskytovat v nějakém předem dohodnutém formátu (určeném
rozhraním komponenty).
14
Základní principy komponentových technologií
Obrázek 2.3: UML komponentový diagram meteorologické stanice
15
3 Komponentové modely
Následující kapitola dává přehled o tom, co je to komponentový model a jaké jsou
základní charakteristiky každého komponentového modelu. Dále se kapitola zaměřuje
na několik zástupců komponentových modelů používaných v různých průmyslových odvětvích (EJB, OSGi) nebo pro účely výzkumu (SaveCCM) a na zástupce kontejneru
používajícího návrhový vzor Inversion of Control (IoC) - PicoContainer. Není účelem
této práce poskytnout dokonalý popis těchto komponentových modelů. Na následujících
stránkách je spíše přehled těchto technologií.
3.1 O komponentových modelech
V předchozí kapitole jsme se věnovali komponentám a jejich popisu, ale aby mohly
komponenty vůbec existovat a komunikovat spolu, musí existovat jasná pravidla, kterými
se komponenty musí řídit. Tato pravidla definuje komponentový model, který umožňuje
komponentám vzájemně interagovat a poskytovat si služby. Komponentový model tvoří
množina typů komponent, jejich rozhraní a specifikace povolených vzorů interakce mezi
typy komponent.
K důležitým vlastnostem komponentových modelů patří, že předepisují a vynucují [3]:
∙ Typy komponent. Komponentový model vyžaduje, aby každá komponenta implementovala jedno nebo více rozhraní. Typ komponenty může pak být definovaný
jako skupina rozhraní implementovaných komponentou. Různé typy komponent
mohou zastávat různé role v systému a mohou být obsaženy v různých schématech interakce (viz dále).
∙ Schémata interakce komponent. Komponentové modely zpravidla předepisují, jaké
je možné použít komunikační protokoly nebo jak je v modelu dosaženo požadované kvality služeb (jako jsou zabezpečení nebo transakce). Dále mohou popisovat,
jak komponenty komunikují mezi sebou nebo s komponentovým frameworkem.
16
EJB
Tato interakční schémata mohou být společná pro všechny typy komponent nebo
naopak specifická jen pro určité typy komponent.
∙ Navázání zdrojů. Proces skládání komponent je věcí navázání komponent na jeden
nebo více zdrojů. . Zdrojem je myšlena služba poskytovaná frameworkem nebo
jinou komponentou, která je nasazena ve frameworku. Komponentový model popisuje, jaké zdroje jsou dostupné pro komponenty a jak se mohou komponenty na
zdroje navázat.
Komponentový model dále obvykle definuje mechanismus, jak vypadá distribuční forma
komponenty a jak je možné komponenty přizpůsobovat a nasadit. To, že komponenty
striktně dodržují komponentový model, odlišuje komponenty (ve smyslu v jakém používáme tento termín) od jiných softwarových entit (např. od balíků software) [3].
Jen dodržovat pravidla předepsaná komponentovým modelem ale nestačí. Potřebujeme ještě prostředí, ve kterém komponenty poběží a které zajistí prostředky pro komunikaci komponent. Toto prostředí nazýváme komponentový framework. Komponentový
framework si můžeme představit jako operační systém pro komponenty. Komponenty
pak mají ve frameworku podobný stav jako aplikace v operačním systému. Narozdíl od
operačních systémů mají frameworky zpravidla menší rozsah a jsou specializovány na
poskytování služeb pro interakci mezi komponentami.1
Komponentové modely svým způsobem definují architekturu výsledného systému. To
může limitovat flexibilitu systému, ale na druhou stranu to zrychluje jeho vývoj.
3.2 EJB
Enterprise JavaBeans (EJB) je architektura, vyvinutá firmou Sun Microsystems, která
má usnadnit vývojářům vytváření rozsáhlých distribuovaných komponentových systémů
v Javě. V současné době existuje verze 3.0 [10], která proti předchozím verzím zjednodušuje vývoj takových systémů a je ve světě Javy velmi populární.
EJB specifikace definuje několik základních typů komponent - bean. Jsou to serverside komponenty, skládající se z jednoho nebo více objektů, nasaditelné v distribuovaném
prostředí. Rozlišujeme session beans a message driven beans. K těmto komponentám
přistupují klienti prostřednictvím rozhraní komponenty, které může být lokální (local
1 Ohledně
komponentových modelů a frameworků existují v literatuře různé termíny (např. component
kit [9]). V této práci je komponentovým frameworkem myšlena implementace služeb, které podporují
a vynucují komponentový model (tzv. podpůrná infrastruktura pro komponenty).
17
OSGi
interface) nebo vzdálené (remote interface). Rozhraní musí splňovat požadavky dané
EJB specifikací, aby bylo možné komponenty spravovat uvnitř EJB kontejneru2 . Ke
komunikaci s těmito komponentami přes remote interface se používá RMI3 .
Navzdory tomu, že se EJB zaměřuje hlavně na funkcionalitu systémů, definuje model
EJB několik charakteristik, které by se daly považovat za mimofunkční podle definice
uvedené v sekci 4.1. Model definuje následující EFP:
∙ Locality - globální charakteristika komponenty, která říká, zda jsou její operace
přístupné vzdáleně nebo pouze klienty stejného kontejneru.
∙ State - session bean může být buď stateless (bezstavová), nebo stateful (stavová).
∙ Transaction demarcation - pro operaci beany definuje očekávanou úroveň podpory transakcí v rozsahu od never (nikdy) do required and mandatory (vyžadovaná, povinná), kde klient musí poskytnout pro operaci transakční kontext.
∙ Security - zahrnuje definici role klienta v přístupu k operacím beany. Beans může
také běžet pod jinou identitou než původní požadavek.
Mimofunkční charakteristiky v EJB jsou popsány buď XML syntaxí v deployment
deskriptoru beany, nebo specifikací, která je založená na Java anotacích.
3.3 OSGi
Tato sekce podává zkrácený přehled komponentové architektury OSGi4 . Více informací
je možné nalézt přímo ve specifikaci OSGi [20, 21].
OSGi AllianceTM je nezávislá, nezisková organizace vytvářející a propagující otevřené
specifikace v oblasti distribuovaných prostředí. Tyto specifikace definují OSGi Service
Platform. Ta se skládá z definice OSGi frameworku a množiny základních služeb.
OSGi framework je postavený na Javě (Java slouží jako běhové prostředí) a jeho cílová platforma zahrnuje set-top-boxy, modemy, spotřební elektroniku, osobní počítače,
automobily, mobilní telefony, atd. Ačkoli od vydání první verze specifikace již uplynulo
skoro deset let, největší rozmach nastal pro OSGi až v posledních několika letech použitím této technologie nejen v embedded zařízeních5 , ale také v desktopových aplikacích
2 EJB
kontejner je aplikační server určený pro nasazení a běh bean.
Method Invocation - Java implementace vzdáleného volání metod.
4 Open Services Gateway initiative
5 vestavěná nebo zabudovaná (většínou jednoúčelová) zařízení
3 Remote
18
OSGi
a aplikačních serverech. V současné době již existuje celá řada frameworků implementujících OSGi. Jsou to např. IBM Websphere, JBoss, ServiceMix, SpringSource a
v neposlední řadě robustní vývojový nástroj Eclipse IDE.
3.3.1 OSGi Service Platform
OSGi představuje konfigurovatelnou platformu vybudovanou nad JVM6 , která poskytuje
prostředí pro běh modulárních aplikací. Specifikace OSGi definuje komponentový model. Jádrem OSGi specifikace je framework, který implementuje tento komponentový
model.
Funkcionalita frameworku je rozdělena do několika základních vrstev, které řeší základní požadavky na komponentový model:
∙ Vrstva komponent (modulů) - Definuje, co je to komponenta a zabývá se problematikou validace, distribuce a nasazení komponent.
∙ Vrstva životního cyklu - Definuje životní cyklus komponent.
∙ Vrstva služeb - Zabývá se službami poskytovanými komponentami a komponentám.
Nepovinně může framework implementující OSGi ještě obsahovat vrstvu zabezpečení.
Vrstva komponent
Komponenta v OSGi se nazývá bundle. Je představována jedním JAR7 souborem, který je
zároveň jednotkou modularizace a nasazení. Tento soubor obsahuje Java třídy a zdroje
(např. obrázky, HTML soubory, soubory nápovědy, atd.), které dohromady s třídami
poskytují nějakou funkčnost uživateli komponenty. Kromě toho JAR soubor obsahuje
manifest, který popisuje obsah souboru a poskytuje informace o komponentě.
V manifestu jsou uvedeny informace o všem, co komponenta poskytuje okolí a
všechno, co od okolí vyžaduje, aby byla správně nainstalována a aktivována. V prostředí OSGi je komponenta brána jako černá skříňka. To znamená, že nás nezajímá její
implementace a přistupujeme k jejím službám přes rozhraní. Komponenty mezi sebou
mohou sdílet Java balíčky (packages), které obsahují. Komponenta může poskytovat (export) svůj balíček nebo využívat (import) balíček jiné komponenty. Soubor manifestu
6 Java
Virtual Machine
ARchive - formát souboru, ve kterém jsou nejčastěji distribuovány Java třídy a k nim přiřazená
meta-data
7 Java
19
OSGi
je povinnou součástí každé komponenty a mimo jiné umožňuje frameworku a ostatním
komponentám zjišťovat informace o konkrétní komponentě.
Vrstva životního cyklu
Komponenta představuje JAR soubor spuštěný v OSGi frameworku. Tato vrstva definuje
operace nad životním cyklem komponenty - jak je možné komponentu nainstalovat,
spustit, aktualizovat a odinstalovat. Správa životního cyklu je jednou z silných stránek
OSGi. Všechny vyjmenované operace je možné nad komponentami provádět dynamicky
za běhu frameworku. Komponenta v OSGi se vždy nachází v jednom z definovaných
stavů (viz obrázek 3.1).
Základními komponentami v OSGi jsou ty, které mohou být nastartovány. Aby mohla
být komponenta nastartována, musí v jedné ze tříd implementovat rozhraní BundleActivator. Tato třída musí být také identifikována v manifestu komponenty jako aktivátor komponenty. Rozhraní BundleActivator obsahuje metody start a stop,
které kontejner volá, aby komponentu spustil popřípadě zastavil. Metoda start spustí
všechna potřebná vlákna pro běh komponenty, metoda stop pak musí provést úklid po
komponentě a ze systému všechna tato vlákna odstranit.
Komponenta nemusí nutně obsahovat aktivátor. V takovém případě není komponenta
spustitelná a kontejner se o její spuštění ani nepokouší. Komponenty bez aktivátoru
mohou být použity pouze jako exportéři tříd nebo rozhraní.
Framework definuje následující stavy:
∙ INSTALLED - Komponenta je úspěšně nainstalována do systému. Znamená to,
že kontejner přečetl její JAR soubor a zkontroloval obsah komponenty (všechny
povinné položky).
∙ RESOLVED - Všechny Java třídy, které komponenta potřebuje, jsou k dispozici.
Tento stav indikuje, že komponenta je buď připravena k nastartování, nebo byla
zastavena.
∙ STARTING - Kontejner zavolal metodu BundleActivator.start a ta právě
běží.
∙ ACTIVE - Komponenta byla úspěšně nastartována a běží. V tomto stavu se komponenta nachází po úspěšném návratu z metody BundleActivator.start.
∙ STOPPING - Komponenta je právě zastavována. Kontejner zavolal metodu BundleActivator.stop a ta právě běží.
20
OSGi
Obrázek 3.1: Stavový diagram životního cyklu komponenty (převzato z [20])
∙ UNINSTALLED - Komponenta byla odinstalována ze systému. Z tohoto stavu
není možné komponentu přesunout do jiného stavu.
Vrstva služeb
Vrstva služeb definuje dynamický spolupracující model silně integrovaný s vrstvou životního cyklu komponent. Jedná se o model publikuj-najdi-navaž, kde poskytovatelé služeb
zveřejní (publikují) popis nabízených služeb, spotřebitelé služeb pak hledají služby, které
potřebují a po nalezení se k nim naváží (připojí).
V OSGi jsou komponenty vystavěny okolo množiny spolupracujících služeb přístupných z registru služeb. Služba v kontextu OSGi definovaná rozhraním služby a implementovaná objektem služby. Rozhraní služby by mělo obsahovat co nejméně implementačních detailů. Objekt služby, což je obyčejná Java třída implementující rozhraní služby,
je vlastněný komponentou a běží uvnitř komponenty. Tato komponenta musí registrovat objekt služby v registru služeb, aby byla funkcionalita objektu přístupná ostatním
komponentám ve frameworku. Závislosti mezi komponentami, které vlastní služby, a
těmi, které je používají, jsou spravovány kontejnerem. Framework se například postará
o odregistrování všech služeb používaných komponentou při jejím zastavení.
Registr služeb umožňuje spotřebitelům služeb nacházet služby dotazy formulovanými
21
SaveCCM
v syntaxi LDAP8 . Framework také zavádí mechanismus zpráv, který umožňuje službám
sledovat změny, které ve frameworku nastávají (např. zaregistrování nové služby nebo
odinstalování služby).
3.4 SaveCCM
3.4.1 Úvod
SaveCCM (The SaveComp Component Model) je komponentový jazyk určený pro modelování embedded zařízení s důrazem na bezpečnost a předvídatelnost [13]. Aplikační
doménou SaveCCM je automobilový průmysl. Byl vyvinut na Mälardalen University ve
Švédsku v rámci projektu SAVE [14].
SaveCCM je založeno na syntaxi XML (popis SaveCCM XML syntaxe naleznete
v příloze A v [13]) a pro grafickou notaci je použita upravená podmnožina UML2
komponentového diagramu (obrázek 3.2). Sémantika je formálně definovaná jako transformace skládající se ze dvou kroků. Prvním krokem je transformace z jazyka SaveCCM
do jazyka SaveCCM Core a druhým pak transformace z SaveCCM Core do timed automata9 s úkoly. V této sekci je stručně popsán pouze komponentový model SaveCCM,
který nás zajímá.
SaveCCM je limitováno na analýzu real-time charakteristik a závislostí ve své aplikační doméně. Je určený pro modelování automobilových systémů s použitím CBD
přístupu a s důrazem kladeným na předvídatelnost a analyzovatelnost.
Systémy jsou v SaveCCM budovány ze vzájemně propojených elementů s definovanými rozhraními, které se skládají z vstupních a výstupních portů. Model je založený
na vzoru řídícího toku (control flow) a striktně odděluje datový tok od řídícího. Datový tok je zachycen spojeními mezi datovými porty, řídící pak spojeními mezi trigger
porty. Existuje ještě třetí typ portu, který kombinuje funkcionalitu obou předchozích
a nazývá se kombinovaný port. Oddělení datového a řídícího toku dovoluje vykonávat
jak periodické tak událostmi řízené aktivity (exekuce může být spuštěna hodinami nebo
externími událostmi).
SaveCCM má zabudovanou podporu pro EFP - s každou komponentou můžou být
svázány charakteristiky jakosti (quality attributes), které poskytují potřebná data pro analýzu komponent. Zajímavé je, že kromě jména a typu mohou charakteristiky obsahovat
8 Lightweight
Directory Access Protocol
(finite) automata [1] je labelled transition system model pro komponenty v real-time systémech.
Používá se k modelování chování real-time systémů v čase.
9 timed
22
SaveCCM
Obrázek 3.2: Grafická notace SaveCCM (převzato z [13])
ještě hodnotu důvěryhodnosti charakteristiky (credibility).
3.4.2 Architektonické elementy
Hlavními architektonickými elementy SaveCCM jsou komponenty, assemblies (viz dále)
a switches (přepínače). Rozhraní všech těchto typů je definováno jako množina portů
představující bod interakce mezi elementem a jeho okolím. Systémy se skládají z těchto
elementů propojováním jejich portů.
Komponenty
Komponenta je hlavní architektonický element v SaveCCM. Obsahuje vstupní a výstupní
porty spolu s množinou charakteristik jakosti (které představují EFP komponenty). Těmito charakteristikami mohou být například odhady spolehlivosti nebo modely bezpečnosti. Používají se pro analýzu, extrakci a syntézu modelu.
Funkcionalita jedné komponenty je typicky implementována jedinou vstupní funkcí
napsanou v jazyce C, ale je možné používat i složitější komponenty, které popisují
několik úkolů. Závislosti mezi komponentami je možné vyjadřovat pouze propojením
portů.
Životní cyklus komponenty začíná ve stavu inactive, ve kterém komponenta zůstane,
dokud nejsou aktivovány všechny její trigger porty. Po aktivaci těchto portů se přesune do stavu executing. Tento stav se skládá z několika fází. První fází je read, kdy
jsou uloženy všechny hodnoty ze vstupních datových portů do vnitřních proměnných.
Následuje fáze execution, ve které jsou vykonány operace nad přečtenými daty a po-
23
SaveCCM
Obrázek 3.3: Komponenty Clock a Delay (převzato z [13])
slední fáze write zapíše výstup těchto operací do výstupních portů a aktivuje všechny
výstupní trigger porty. Po té se komponenta vrací do stavu inactive. Tato striktní sémantika (přečíst-vykonat-zapsat) zajišťuje nezávislost vykonání komponenty na jakékoliv
souběžné aktivitě [13].
Hodiny a zpoždění
V SaveCCM jsou k dispozici dvě speciální komponenty určené pro ovlivnění časování
triggerů (spouštěčů) - Clock (hodiny) a Delay (zpoždění). Komponenta Clock je generátor triggerů a její jediný port je výstupní trigger port. Má parametry T (perioda) a J
(jitter - odchylka od periodického signálu). Nová perioda začíná každých T časových
jednotek a trigger je vygenerován během J časových jednotek po začátku této periody.
Komponenta Delay má jeden vstupní trigger port a jeden výstupní trigger port. Dva
parametry D (delay - zpoždění) a P (precision - přesnost) jsou pak použity k pozdržení
trigger signálu o D až D+P časových jednotek.
Kompozitní komponenty
Kompozitní komponenta je speciální typ komponenty, jejíž chování je popsáno propojením komponent namísto vstupní funkce. Kompozitní komponenta je sama komponentou.
To znamená, že je dodržena striktní sémantika přečíst-vykonat-zapsat a platí stejná pravidla pro její životní cyklus.
Přepínače
Přepínače (switches) slouží k změně zapojení komponent. Obsahují množinu mapování
ze vstupních portů na výstupní. Každému z těchto propojení je přiřazen logický výraz,
jehož proměnnými jsou hodnoty vstupních portů přepínače. Tento výraz vyhodnocuje,
zda je dané mapování aktivní. Přepínače přeposílají data na výstupní porty ihned po
jejich obdržení a na rozdíl od komponent nejsou aktivovány.
24
PicoContainer
Assemblies
Assemblies jsou prostředkem k zapouzdření, pojmenování a skrytí vnitřní struktury
propojení více komponent. Stejně jako přepínače nejsou nijak aktivovány a rovnou přeposílají data ze vstupních portů na výstupní.
Porty a konexe
Jak je uvedeno výše, SaveCCM rozlišuje mezi vstupními a výstupními a mezi datovými
a trigger porty. Všechny porty mají své jméno, datové pak navíc typ a nepovinně ještě
počáteční hodnotu. Externí port je pak port, který má navíc popisek mapující tento port
na nějakou externí entitu a který není propojený s ostatními porty.
Porty jsou vzájemně propojeny jedním ze dvou typů konexí (connections). Prvním
typem jsou immediate connections, které představují bezztrátový přenos dat z jednoho
portu na druhý. Druhým typem jsou pak complex connections, které představují přenos
dat (nebo řízení) skrz kanál s možnou ztrátou nebo zpožděním přenášených informací.
3.5 PicoContainer
PicoContainer [15] je open-source light-weight kontejner založený na návrhovém vzoru
Inversion of Control (dále jen IoC), používající princip Dependency Injection (dále jen
DI)[11]. Projekt začal v roce 2003 a dal vzniknout principu constructor injection autowiring10 . Mezi hlavní přednosti tohoto kontejneru patří jeho velikost (jádro má pouze
260kB), podpora různých typů DI připojitelnost kontejneru k projektu (embeddability).
Kromě constuctor injection podporuje PicoContainer ještě různé jiné typy DI. Jedním
z těchto typů je setter injection auto-wiring.
Setter injection je typ DI, kde kontejner předává komponentě její závistlosti za použití
tzv. setterů po instancování komponenty. Setter je metoda s přesně definovaným jménem
a jediným parametrem, který představuje injektovaný objekt. V ostatních metodách třídy
pak můžeme použít tyto objekty, aniž bychom je ručně instancovali.
Příklad na setter injection (převzato z [15]):
p u b l i c c l a s s Apple {
p r i v a t e Orange o r a n g e ;
private Pear pear ;
10 Varianta
DI, kde komponenty dostávají všechny závislosti přes svůj konstruktor
25
PicoContainer
p r i v a t e Banana b a n a n a ;
p u b l i c s e t O r a n g e ( Orange o r a n g e ) {
t h i s . orange = orange ;
}
public s e t P e a r ( Pear pear ) {
this . pear = pear ;
}
p u b l i c s e t B a n a n a ( Banana b a n a n a ) {
t h i s . banana = banana ;
}
public void i n i t i a l i z e ( ) {
/ / a l l s e t X X X s a r e now done
}
/ / o t h e r methods
}
26
4 Specifikace mimofunkčních
charakteristik
Většina výzkumu v oblasti softwarových komponent se zaměřuje na popis funkčních
aspektů komponent (jako např. specifikace komponenty, testů, atd.) [2].
Tato kapitola se blíže věnuje popisu charakteristik komponent, které nepopisují funkční
aspekty komponent, ale to, jak se systém chová s ohledem na pozorovatelné charakteristiky. Tyto charakteristiky jsou například výkon, znovupoužitelnost nebo spolehlivost.
4.1 Definice EFP
Na mimofunkční charakteristiky je možné nahlížet z různých pohledů. Jen samotný
termín extra-functional property nemá standardizovanou definici. Nejčastěji používaná
synonyma pro EFP jsou „kvalitativní atributy, charakteristiky nebo faktory“ [16]. Pro
účely této práce je použita definice mimofunkčních charakteristik z [16]:
Mimofunkční charakteristika softwarového modulu je taková charakteristika, která:
(1) je důležitá pro klienty nebo dokonce koncové uživatele modulu a
(2) není vyvolatelnou funkcionalitou nebo chováním.
4.2 Přístupy k EFP
Tato sekce popisuje dva různé publikované přístupy k EFP ve vztahu k CBSE. Záměrem
není popsat všechny dostupné studie o EFP, ale pouze ukázat některé hlavní přístupy ke
specifikaci EFP.
27
Přístupy k EFP
4.2.1 NoFun
Jazyk NoFun [12] se zaměřuje na popis mimofunkčních informací v oblasti komponentového programování a jejich vazbu na softwarové moduly. Identifikuje tři typy těchto
informací: Non-functional attribute, Non-functional behaviour a Non-functional requirement 1 (viz dále).
Non-functional Attributes
Jedná se o jakékoliv atributy softwarového celku, které slouží k jeho popsání nebo vyhodnocení. Tyto atributy jsou součástí domény, která definuje množinu platných hodnot
a operací. Autoři identifikují domény jako standardní datové typy Boolean, Integer, Real,
String nebo Enumeration. Atributy mohou být základní nebo odvozené. Odvozené atributy jsou odvozené ze základních. Dále mají obor působnosti, který určuje, v jakých
komponentách je atribut použit. Každý atribut může být vázán k celé komponentě nebo
k jednotlivé operaci.
Non-functional Behaviour
V jazyce NoFun je oddělena aplikace EFP na určitou implementaci komponenty od
jejich definice. Non-functional behaviour je jakékoliv přidělení hodnot k non-functional
attributes, které jsou použity v implementované komponentě.
Non-functional Requirements
Toto se uplatní v případě skládání komponent. Pokud jedna komponenta importuje druhou, musí si vybrat správnou implementaci importované komponenty. Specifikuje nonfunctional requirements, což je podmnožina non-functional behaviour, které od importované komponenty požaduje. Podle shody non-functional requirements s non-functional
behaviour pak importující komponenta vybere vyhovující implementaci importované
komponenty.
4.2.2 Component Quality Model
I když je nadefinováno, jak mimofunkční charakteristiky popsat, stále ještě zbývá definovat, jaké konkrétní mimofunkční charakteristiky lze rozeznávat. Autoři práce [2]
kategorizují atributy jakosti, které je možné použít jako EFP. Vycházejí při tom z normy
1 Mimofunkční
charakteristika, chování a požadavek
28
Přístupy k EFP
ISO/IEC 91262 , kterou upravili pro potřeby CBD. Výsledný model jakosti komponenty
(dále jen CQM - Component Quality Model) se skládá z následujících charakteristik:
∙ Funkcionalita (Functionality): schopnost komponenty poskytovat vyžadované
služby
∙ Spolehlivost (Reliability): schopnost komponenty udržet určitou úroveň výkonu
∙ Použitelnost (Usability): vyjadřuje, jak je komponenta pochopitelná, naučitelná,
použitelná, konfigurovatelná a vykonavatelná
∙ Efektivnost (Efficiency): schopnost komponenty poskytnout požadovanou výkonnost v závislosti na objemu použitých zdrojů
∙ Udržovatelnost (Maintainability): vyjadřuje, jak možné komponentu modifikovat
∙ Přenositelnost (Portability): vyjadřuje, jak je komponenta schopná přenosu z jednoho prostředí do druhého
∙ Prodejnost (Marketability): vyjadřuje tržní charakteristiky komponenty
Charakteristiky se dále dělí na sub-charakteristiky související s běhovým prostředím
komponenty (runtime) a s jejím životním cyklem (life-cycle).
CQM popisuje jakostní atributy pro měření sub-charakteristik komponent. Každý
z těchto atributů definuje metriku, která popisuje metodu měření a jednotky.
CQM popisuje následující druhy metrik:
∙ Presence (P): Identifikuje přítomnost atributu v komponentě. Skládá se z logické
hodnoty (boolean) a textového řetězce (string). Logická hodnota indikuje přítomnost atributu a textová pak popisuje, jak je atribut implementovaný komponentou
(pokud je přítomný).
∙ IValues (IV): Indikuje přesné hodnoty. Je popsána jako číselná proměnná (integer)
a textový řetězec (string), který určuje jednotku proměnné (např. kb, MHz, atd.).
∙ Ratio (R): Tato metrika se používá k vyjádření percentuální hodnoty. Je popsána
jako číselná proměnná (integer) s hodnotami mezi 0 a 100.
2 Jedná
se o obecný standardizovaný model jakosti software, který může být aplikován na jakýkoliv
softwarový produkt.
29
Přístupy k EFP
Kromě uvedených charakteristik definují autoři ještě dodatečné informace, které se skládají z technických informací (verze komponenty, programovací jazyk, atd.) a organizačních informací (CMMI úroveň a reputace organizace). Tyto informace jsou důležité pro
vývojáře, aby dokázali analyzovat současný stav komponenty, a pro také pro zákazníky
komponenty (například komponenta vyvinutá organizací s CMMI úrovní 5 bude pravděpodobně spolehlivější, než komponenta vyvinutá neznámou firmou). K popisu informací
se používá textový řetězec.
30
5 CoSi - návrh rozšíření
komponentového modelu
Záměrem této diplomové práce je seznámit se s komponentovým modelem CoSi1 , vyvinutým v rámci diplomové práce „Implementace jednoduchého komponentového modelu“ [22] Břetislavem Wajtrem a Ing. Přemyslem Bradou, Msc., Ph.D. a navrhnout a
implementovat rozšíření tohoto komponentového modelu o popis mimofunkčních charakteristik komponent a o balíky komponent. Hlavním úkolem CoSi je napomáhat při
výzkumu verzování a nahraditelnosti komponent. Přidání EFP do CoSi umožní napomáhat i ve výzkumu nahraditelnosti komponent na základě těchto charakteristik.
Balíky komponent pak mají v tomto kontextu za úkol zjednodušit nasazení sdružováním spolu souvisejících komponent do větších celků. V kapitole 6 je popsána specifikace
CoSi v její aktuální podobě (verze 2.0) se zakomponovanými rozšířeními komponentového modelu. Tato specifikace předepisuje, co musí implementace komponentového
frameworku obsahovat, aby byla považována za implementaci CoSi a aby bylo možné
v této implementaci použít komponenty vyvinuté pro CoSi. Nová verze specifikace
vznikala zároveň s návrhem rozšíření popsaných v této práci.
Abychom oddělili mou práci od práce p. Brady a p. Wajtra, uvedeme zde kroky, ze
kterých se skládala realizace této práce:
∙ důkladné seznámení se se specifikací a implementací komponentového modelu
CoSi včetně jeho kritické analýzy (tato část byla velmi důležitá pro korektní návrh
změn v implementaci),
∙ návrh rozšíření modelu o EFP,
∙ návrh rozšíření modelu o balíky komponent,
∙ návrh změn referenční implementace CoSi pro podporu těchto rozšíření,
1 Components
simplified
31
Obecně o CoSi
∙ implementace změn a ukázkových scénářů pro otestování nově implementovaných
rozšíření.
5.1 Obecně o CoSi
CoSi je obecně použitelný komponentový framework založený na Javě. Jako zdroj inspirace pro CoSi sloužil komponentový model OSGi [20]. Následující sekce popisuje
meta-model a termíny používané v CoSi.
5.1.1 Meta-model CoSi
Komponentový model CoSi se skládá z entit vyobrazených na obrázku 5.1. Entity označené stereotypem "new" jsou ty, které byly přidány v CoSi verze 2 v rámci této diplomové
práce. Základem je komponenta2 , která má svého poskytovatele, jméno a verzi. Tyto tři
parametry jednoznačně identifikují komponentu. Komponenta je nasazena do kontejneru, který tvoří běhové prostředí pro komponenty. Komponenta dále může poskytovat
nebo vyžadovat vlastností (features), které mají jméno, typ a další nepovinné atributy
jako například verzi. Různé vlastnosti komponenty, které mají stejný typ, jsou rozlišeny
jejich jmény.
Meta-model CoSi definuje tyto čtyři druhy vlastností:
Služba (service) je specifikována rozhraním v Javě a implementuje funkčnost. Poskytované služby jsou registrovány v kontejneru. Ten dále zprostředkovává navázání
poskytovaných služeb na komponenty, které služby vyžadují. Toto navázání je
realizované objekty typu odkaz na službu.
Typ (type) odkazuje na třídu nebo rozhraní jazyka. Typy poskytované komponentami
jsou přístupné komponentám, které dané typy vyžadují přes class loader (viz
sekce 6.4) exportující komponenty.
Události (events)3 umožňují vyměňování zpráv mezi komponentami. Kontejner poskytuje službu zajišťující příjem a doručování zpráv komponentám. Události mají
typ a jméno, což umožňuje komponentám specifikovat filtry, které říkají, jaké události bude komponenta poslouchat. Doručovat zprávy v CoSi je možné synchronně
i asynchronně.
2v
CoSi komponenty nazýváme také bundle
32
Obecně o CoSi
Obrázek 5.1: Meta-model CoSi
Atributy (attributes) jsou typované hodnoty, které může komponenta číst nebo zapisovat. Mohou být pouze pro čtení (read-only) nebo pro čtení i zápis (read-write).
Atributy jsou přístupné přes registr atributů udržovaný kontejnerem.
5.1.2 Obsah komponenty
V následujícím textu je popsána distribuční forma komponenty a způsoby komunikace
komponenty s kontejnerem a s ostatními komponentami.
Komponenta je v CoSi softwarový celek distribuovaný ve formě jednoho JAR archivu, který obsahuje vše, co komponenta k běhu potřebuje. Je v něm uložen přeložený
kód komponenty, všechna rozhraní a zdroje, které komponenta využívá. Zdroji mohou
být například knihovny třetích stran, multimediální soubory (ikony, obrázky), textové
soubory, apod.
33
Mimofunkční charakteristiky
Komponenty v CoSi se pro okolí chovají jako černá skříňka (black-box). Znamená
to, že pokud komponenta nespecifikuje v manifestu komponenty jinak, nemůže využívat
žádné zdroje, které nejsou obsaženy v jejím JAR archivu. Stejně tak nikdo mimo komponentu nemůže využívat žádné zdroje této komponenty, pokud nejsou nadefinované jako
exportované. Ale neplatí to jen pro zdroje komponenty. Také implementace komponenty
je před jejím okolím skryta. Kontejner a ostatní komponenty mají možnost zjistit, co
komponenta dělá (přes rozhraní komponenty), ale už ne jakým způsobem.
Manifest komponenty je textový soubor, který používá ke specifikaci informací o komponentě hlavičky (headers). Těmito informacemi jsou např. název komponenty, verze,
závislosti, class path, atd. Během instalace komponenty do systému čte tento soubor, a
na základě takto získaných metadat integruje komponentu do systému. Soubor manifestu
obsahuje mimo jiné informace o:
∙ aktivátoru komponenty - třída, kterou kontejner používá ke spuštění a zastavení
komponenty;
∙ službách - poskytované a vyžadované služby (rozhraní);
∙ typech - komponenta může poskytovat některé z jejích tříd ostatním komponentám
nebo využívat třídy jiných komponent;
∙ událostech - komponenta specifikuje události, které bude odesílat nebo umět přijímat;
∙ atributech - komponenta může nastavit systémovou proměnnou (atribut), kterou
mohou ostatní komponenty číst.
Jako výsledek této DP framework CoSi od verze 2.0 umožňuje jednoúrovňové skládání
komponent do balíků komponent (viz sekce 5.3) za účelem jednoduššího nasazení většího počtu komponent. Nejedná se o skládání ve smyslu hierarchického komponentového
modelu, kdy výsledkem složení více komponent je také komponenta, ale o zabalení více
komponent tvořících jeden funkční celek, do balíku komponent. Tento balík komponent je pak možné do systému nainstalovat jako celek, čímž se nainstalují jednotlivé
komponenty v něm obsažené. Komponenty pak vystupují v systému samostatně.
5.2 Mimofunkční charakteristiky
Specifikace EFP pro CoSi vznikala na Katedře informatiky a výpočetní techniky Fakulty
aplikovaných věd Západočeské univerzity v Plzni současně s touto diplomovou prácí a
34
Mimofunkční charakteristiky
její základní koncepty jsou popsány v [16]. V této části jsou popsána výsledná rozšíření
CoSi v rámci diplomové práce.
5.2.1 Obecné principy
Jedním z hlavních cílů diplomové práce je rozšíření existujícího CoSi frameworku o možnost rozšíření popisu komponent a jejich služeb o mimofunkční charakteristiky. Jak bylo
ukázáno v kapitole 4, koncept EFP není zatím ustálený a neexistují jednotné definice a
návody, jak EFP začlenit do modelu.
Protože jednou z hlavních předností CoSi je jednoduchost, nesmí zavedení EFP do
modelu vnést složité nebo těžko pochopitelné postupy. Další z předností modelu je
obecnost - protože je model CoSi primárně používaný při výzkumu nahraditelnosti
komponent, měly by být výsledné EFP schopné zachytit co nejširší rozsah charakteristik
používaných v různých doménách od real-time embedded systémů (což je doména například SaveCCM - viz sekce 3.4) až po charakteristiky rozsáhlých enterprise systémů
(což je doména EJB - viz sekce 3.2).
Z použití při výzkumu nahraditelnosti také vyplývá, že by EFP měly být strojově
čitelné a analyzovatelné, aby bylo možné proces výběru vhodných komponent na základě
EFP automatizovat. Strojová čitelnost je také důležitá pro verifikaci EFP.
5.2.2 Definice EFP
Model EFP pro CoSi vychází z konceptů uvedených v kapitole 4. Navržené mimofunkční charakteristiky tak přibližně odpovídají jakostním atributům v CQM [2] nebo
non-functional attributes v jazyce NoFun [12]. Na rozdíl od NoFun současný model
EFP v CoSi obsahuje pouze charakteristiky odpovídající základním charakteristikám,
ale s odvozenými charakteristikami se počítá až v další verzi modelu (viz [16]).
Následováním myšlenky jednoduchosti byla definována mimofunkční charakteristika
jako dvojice (jméno, typ). Jméno značí název charakteristiky (například response_time)
a typ pak možné hodnoty, které popisují charakteristiku. K popisu je možné použít
skalární typy (boolean, integer, float, token a string) nebo komplexní typy (enumeration,
interval a map).
Skalární typy boolean, integer a float slouží k popisu měřitelných hodnot charakteristik. Typ token odpovídá identifikátoru může vyjadřovat jednoduché vlastnosti komponenty jako například typ zabezpečení (ssl). Typ enumeration je výčtem skalárních
typů stejné hodnoty a může popisovat například to, jaké komponenta podporuje ope-
35
Mimofunkční charakteristiky
rační systémy (windows, unix, macos). Interval je použitelný například pro specifikaci
minimální požadované paměti (memory > 10) a poslední typ map, který je definovaný
jako dvojice (identifikátor, hodnota), může vyjadřovat například náročnost komponenty
na systémové zdroje (disk.space = 10, memory = 50). Podrobněji jsou tyto typy popsány
ve specifikaci CoSi v sekci 6.1.2.
5.2.3 Registr EFP
Definice EFP sice stačí k popisu charakteristiky, ale je žádoucí, aby se stejnými charakteristikami bylo nakládáno stejně. Představme si charakteristiku popisující použitý
algoritmus šifrování dat, která může nabývat hodnot rsa, des, 3des, blowfish, seal a rc4.
Mechanismus, který umožní specifikovat, jakých hodnot může konkrétní charakteristika
nabývat, se v CoSi nazývá registr mimofunkčních charakteristik.
Tento registr obsahuje informace o charakteristice uvedené v sekci 5.2.2 (jméno, typ)
spolu s dodatečnými informacemi, jako jsou konkrétní hodnoty, kterých může charakteristika nabývat. Použití takové charakteristiky při specifikaci komponenty vyžaduje uvést
pouze její jméno, což je v souladu s požadavkem na jednoduchost. Zjednodušeně by se
dalo říci, že registr obsahuje kompletní definice všech použitelných typů charakteristik.
Syntax a použití registru je více popsáno v sekci 6.1.3.
5.2.4 Popis EFP
Stejně jako NoFun umožňuje CoSi specifikovat EFP pro jednotlivé komponenty nebo
pouze pro jejich část (v současné verzi CoSi je možné specifikovat EFP pro služby
komponenty, ale v budoucích verzích CoSi se počítá i s možností specifikovat EFP pro
další vlastnosti komponenty).
Protože CoSi používá pro popis komponent soubor manifestu komponenty (viz sekce
6.1.2), bylo logickým krokem začlenit popis EFP přímo do tohoto souboru. To, jestli
je charakteristika svázána s celou komponentou nebo s konkretní službou, nazýváme
kontext charakteristiky. Pro charakteristiky svázané s konkrétní službou rozeznáváme
vyžadované EFP a poskytované EFP. Dále potřebujeme znát název a hodnotu charakteristiky, pro které platí následující pravidla:
1. Název charakteristiky se musí shodovat s jedním z názvů obsažených v registru
EFP (viz výše).
36
Balíky komponent
2. Konkrétní hodnota charakteristiky musí být stejného typu, jaký je pro danou charakteristiku definován v registru, a zároveň musí nabývat pouze hodnot definovaných na stejném místě.
3. Hodnota poskytovaných EFP může být vyjádřena pouze operátorem „rovná se“
(například memory = 10) a hodnota vyžadovaných EFP může být vyjádřena navíc
operátory porovnání (<, >, ≤, ≥).
Charakteristika splňující body uvedené výše se nazývá validní. Příklady a syntax popisu
EFP v manifestu komponenty jsou popsány v definici hlavičky Bundle-Extrafunc
sekce 6.1.2.
5.2.5 Porovnávání EFP
Jedním ze způsobů, jak v CoSi skládat komponenty, je specifikování poskytovaných a
vyžadovaných a služeb (viz sekce 6.1.1). Služby jsou následně navazovány podle jejich
verze, jména, atd. S uvedením EFP do CoSi přibyla povinnost zabývat se při navazování
služeb i těmito charakteristikami.
Aby bylo možné vyhodnotit, zda poskytované EFP jedné služby vyhovují vyžadovaným EFP druhé služby (a tím je možné služby navázat), je nutné definovat proces
porovnávání mimofunkčních charakteristik. Na vyžadované EFP se můžeme dívat jako na
množinu vlastností, které musí služba splnit. Proces porovnávání EFP použije operátor
svázaný s hodnotou vyžadované EFP na hodnotu poskytované EFP. Pokud je výsledek
operace vyhodnocen jako pravda, lze dané služby navázat.
5.3 Balíky komponent
V případě návrhu rozšíření CoSi o balík komponent (v rámci diplomové práce) se nabízelo několik možností, jak k problematice přistupovat. Jednou z možností bylo přeměnit
CoSi v hierarchický komponentový model (jako je například SOFA [7]) a zacházet s
balíky komponent stejně jako s komponentami. Druhou možností bylo adoptovat princip
použitý například v SaveCCM (viz sekce 3.4) – zacházet s balíky komponent jako s
jednotkou deploymentu, bez většího runtime významu balíků. V rámci zachování jednoduchosti komponentového modelu CoSi byla vybrána druhá možnost.
Balíky komponent nazýváme (stejně jako v SaveCCM) assemblies4 a mají následující
4 jeden
balík komponent se nazývá assembly
37
Další rozšíření modelu
vlastnosti:
∙ umožňují sdružovat komponenty do celků
∙ umožňují specifikovat vazby mezi komponentami obsaženými uvnitř balíku
∙ jsou ploché - mohou obsahovat pouze komponenty, ne balíky komponent
∙ jsou jednotkou deploymentu, instalace a odinstalace
∙ umožňují specifikovat pořadí deploymentu komponent obsažených v balíku
∙ nejsou s nimi svázány mimofunkční charakteristiky
∙ je povoleno specifikovat a navazovat vazby mezi komponentami uvnitř a vně balíku
Podrobněji jsou balíky komponent popsány v částech 6.1 a 6.2.
5.4 Další rozšíření modelu
5.4.1 Poskytované a vyžadované balíky Java tříd
Kromě mimofunkčních charakteristik a balíku komponent byl model CoSi v rámci
práce rozšířen ještě o možnost specifikování poskytovaných (vyžadovaných) balíků (viz
sekce 6.1.2). V tomto kontextu balíky nejsou balíky komponent, ale klasické Java packages. Rozšíření má primárně za úkol zjednodušit a zkrátit zápis poskytovaných typů u
komponent. Poskytnutí balíku komponenty odpovídá exportování všech veřejných tříd v
daném balíku, které nejsou exportovány jiným způsobem (například jako služby).
Vyžadování balíku v CoSi znamená, že komponenta předpokládá, že jsou k dispozici
veškeré třídy tohoto balíku. Toto rozšíření ale není doporučeno používat, protože by
mohlo vést k chybám za běhu kontejneru. Představme si scénář, kdy autor komponenty
vyžaduje nějaký konkrétní balík. V době vytváření komponenty má k dispozici komponentu exportující tento balík a používá třídy z tohoto balíku. Autorova komponenta
je následně nasazena do systému, ve kterém je jiná verze komponenty exportující balík
s pozměněnými (nebo chybějícími) třídami, než se kterou počítal autor při vytváření
své komponenty. Pokud autor specifikuje pouze importování balíku bez udané verze,
toto navázání může způsobit chyby za běhu komponenty (například nenalezení třídy
z balíku).
Pokud chce autor komponenty i přesto použít importování balíku, měl by vždy uvést
verzi importovaného balíku. Toto chování ale není vynucené kontejnerem ani specifikací.
38
Další rozšíření modelu
5.4.2 Dependency injection
Při návrhu balíku komponent vyvstala otázka, jak vyjádřit propojení komponent uvnitř
balíku a zároveň jak zamezit, aby se komponenty propojily s jinými komponentami, než
bylo autorem balíku zamýšleno (například s komponentami již přítomnými v kontejneru). K tomuto účelu byl v CoSi přijat princip dependency injection (DI), konkrétně
forma DI setter injection (viz sekce 3.5), používaná hlavně v kontejneru Spring nebo
PicoContainer. Jedná se o injektování instance služby použitím přesně definovaného
setteru - metody, která má jako jediný parametr rozhraní služby a ve svém těle pouze
uloží instanci rozhraní služby do předem připravené proměnné.
Každá komponenta v CoSi může u poskytované služby uvést také její jméno (atribut name). Pokud komponenta vyžaduje nějakou službu (a zná předem její konkrétní
jméno), je obvyklé, že bude také potřebovat instanci této služby. V původní verzi CoSi
musel autor komponenty v jejím kódu zavolat metodu kontejneru pro získání instance
této služby a až pak mohl službu používat. Zavedením atributu autowire u pojmenovaných služeb dává kontejner možnost autorovi komponenty napsat pouze kód setteru
této služby a o více se nestarat. Kontejner před spuštěním komponenty injektuje instanci
této služby do předem připravené proměnné této komponenty zavoláním setteru.
Předpoklady pro použití DI pro navázání dvou služeb komponent jsou následující:
∙ komponenta poskytující službu musí mít v manifestu služby v hlavičce ProvideServices vyplněný atribut name
∙ komponenta vyžadující službu musí mít v manifestu služby v hlavičce RequireServices vyplněný atribut name a zároveň musí mít u služby uvedený atribut
autowire=“true“
∙ komponenta vyžadující službu musí v aktivátoru komponenty implementovat metodu setteru služby
Příklad hlavičky Require-Services pro vyžadovanou službu registry:
Require - S e r v i c e s : cz . zcu . fav . kiv . s e n s o r r e g i s t r y .
S e n s o r R e g i s t r y ; name =" r e g i s t r y "; a u t o w i r e =" true "
Setter služby
Setter služby má jediný parametr - rozhraní injektované služby. Kontejner zavolá tento
setter po vytvoření instance aktivátoru komponenty a před spuštěním komponenty. Název
39
Další rozšíření modelu
setteru služby vychází z parametru name a musí mít přesně definované jméno, aby
kontejner věděl, jakou metodu má pro injektování dané služby použít. Jméno setteru se
skládá ze slova „inject“ následovaného názvem služby (atribut name), u kterého se změní
počáteční písmeno na velké (pokud již velké nebylo). Pro službu s name=“registry“
by kód setteru vypadal následovně:
private SensorRegistry service ;
public void i n j e c t R e g i s t r y ( S e n s o r R e g i s t r y s e r v i c e ) {
this . service = service ;
}
Pro použití setteru může aktivátor komponenty obsahovat privátní proměnnou, do
které se instance služby uloží. V tomto příkladu je to proměnná service. Je i možné
nechat tělo této metody prázdné a nijak s instancí služby nepracovat. Pokud je však
uvedený atribut autowire=“true“, musí aktivátor komponenty metodu obsahovat.
40
6 Specifikace CoSi
Specifikace CoSi je formální specifikací pro implementaci obecně použitelného Java
frameworku, jehož hlavním cílem je umožnit vývoj a běh aplikací založených na komponentách. Vychází ze specifikace OSGi (viz sekce 3.3), přebírá z ní některé prvky a
některé zcela vypouští. V této kapitole je popsána část specifikace CoSi ve verzi 2.0,
která je výsledkem rozšíření navržených a implementovaných v této diplomové práci.
Předchozí verze specifikace nalezneme v [6] a [22].
Specifikace se skládá z popisu:
∙ komponent - co je to komponenta, co obsahuje, jak napsat komponentu a jak může
komponenta komunikovat s ostatními komponentami.
∙ kontejneru - kontejner zajišťuje běhové prostředí pro všechny komponenty. Do kontejneru jsou komponenty nahrávány a probíhá tam jejich životní cyklus. V kontejneru jsou všechny dostupné informace o komponentách. Komponenty zde mohou
také získávat odkazy na služby.
∙ základních služeb - implementace kontejneru musí poskytovat tři základní služby.
Tyto služby zajišťují jednoduché API kontejneru, komunikaci komponent na základě zasílání zpráv a možnost použit mimofunkční charakteristiky při popisu
komponent.
Uvedené části spolu se souborem pravidel uvedeným dále v této kapitole představují
framework. Framework umožňuje vytváření aplikací založených skládání nezávislých
komponent a poskytuje prostředky pro jejich instalaci, provázání, spuštění a odinstalaci.
Všechny tyto úkony lze provádět za běhu systému (dynamicky) bez nutnosti systém
rekompilovat nebo zastavovat.
6.1 Komponentový model CoSi
Tato sekce popisuje specifikaci jádra CoSi - komponentového modelu. Dává přehled
o komponentách a jejich popisu, třídách, které obsahují, jejích meta-datech a distribuční
41
Komponentový model CoSi
formě. Také se zaměřuje na balíky komponent. Součástí specifikace komponentového
modelu je i popis meta-modelu CoSi (viz sekce 5.1.1) a popis obsahu komponenty (viz
sekce 5.1.2).
6.1.1 Obsah komponenty - podrobněji
Tato sekce je pokračováním sekce 5.1.2. Specifikuje podrobněji vlastnosti komponenty.
Aktivátor komponenty
Na rozdíl od OSGi je každá komponenta v CoSi je považována za spustitelnou (runnable). To ukládá komponentě povinnost v jedné ze svých tříd implementovat rozhraní
BundleControl (viz sekce 6.3.1), které obsahuje metody start() a stop().
Právě těmito metodami kontejner startuje a zastavuje všechny komponenty integrované
do systému.
To, které třída implementuje rozhraní BundleControl, je specifikováno v povinné
hlavičce manifestu Control-Class. Kontejner nenainstaluje komponentu, která neobsahuje některou z povinných hlaviček.
Služby
Jedním ze způsobů komunikace komponent v CoSi jsou služby. Služba je část komponenty, která je zveřejněna okolí a poskytuje funkčnost. Systém služeb je úzce provázaný
z životním cyklem komponent (viz sekce 6.2).
O správu služeb se stará registr služeb, do kterého se služby registrují ve formě
rozhraní, pod kterým vystupuje Java objekt služby. Komponenty mohou do toho registru
registrovat své služby nebo hledat služby obsažené v registru, které chtějí používat.
Služba je v CoSi definována jejím rozhraním a implementována jako instance služby.
Instance služby je vlastněna a běží uvnitř komponenty, která službu zaregistrovala. Aby
bylo možné instanci služby používat, musí být zaregistrována v registru služeb. Tím je
zajištěno, že sdílení služeb je kontrolováno kontejnerem.
Kontejner také spravuje závislosti mezi komponentami poskytujícími služby a komponentami používajícími služby. Kontejner například zajišťuje, že komponenta nebude
zastavena, pokud jiné komponenty využívají její služby. Stejně tak nebude komponenta
spuštěna, pokud vyžaduje nějakou službu, ale tato služba není přítomná v registru služeb.
42
Komponentový model CoSi
ServiceReference Každá služba má v registru služeb přiřazený objekt typu ServiceReference, který obsahuje vlastnosti služby a její další meta-data. Komponenty používají
tyto objekty pro zjištění informací o registrovaných službách nebo k tomu, aby vybraly
nejvhodnější službu pro jejich potřeby. Tímto způsobem mohou komponenty zjišťovat
informace o službách, aniž by se vytvářely vazby mezi komponentami. To je vhodné,
pokud komponenta potřebuje informace o službě, ne však její instanci. Pokud komponenta přece jen potřebuje instanci služby, může o ni požádat kontejner zavoláním metody
BundleContext.getService(ServiceReference).
Rozhraní služby Rozhraní služby je specifikace veřejných metod této služby. Programátoři vytvářejí instance služeb z objektů implementujících rozhraní služby a registrují
tyto objekty v registru služeb. Metody instance služby jsou pak přístupné voláním metod
rozhraní služby. Ostatní komponenty mají přístup pouze k tomuto rozhraní, typ instance
služby je před nimi skrytý.
Poskytované (exportované) služby musí být uvedeny v manifestu komponenty (viz
sekce 6.1.2) v hlavičce Provide-Services, vyžadované (importované) služby pak
v hlavičce Require-Services.
Typy
Složitější služby často musejí spolu s typem rozhraní exportovat i další doplňkové typy.
Představme si, že exportujeme službu, která získává data z databáze. Ty ale mají svůj
speciální formát (speciálního typ). Tento typ je proto také součástí služby a je nutné ho
exportovat, aby bylo možné službu využívat.
Exportované typy jsou specifikovány v hlavičce manifestu Provide-Types, importované pak v hlavičce Require-Types. Kontejner zajistí, že komponenta nebude
nainstalována, pokud v systému nejsou přítomny typy, které komponenta importuje.
Události
Dalším typem komunikace mezi komponentami je systém událostí (zpráv). Framework
poskytuje standardní službu MessageService, která se o posílání a přijímání zpráv
stará.
Zpráva je Java objekt dědící od abstraktní třídy Message, kterou poskytuje kontejner.
Každá komponenta, která chce využívat systém zpráv, musí importovat typ Message a
službu MessageService. Zpráva je identifikována svým jménem, což je jednoduchý
43
Komponentový model CoSi
řetězec, který zprávu zároveň popisuje, a typem. Typ zprávy je jméno třídy komponenty
implementující třídu Message. Dále zpráva obsahuje vlastnosti - soubor párů klíčhodnota, který upřesňuje informace o zprávě.
Aby mohla komponenta odeslat zprávu, musí uvést její typ a jméno v hlavičce manifestu Generate-Events, vytvořit za běhu instanci zprávy, získat instanci služby
MessageService a následně poslat zprávu metodou sendMessage() nebo postMessage().
Metoda sendMessage() je blokující (synchronní) - volání metody neskončí, dokud všichni příjemci zprávu neobdrží. Metoda postMessage() je pak asynchronní
- volání metody pouze předá zprávu službě MessageService a ihned potom dochází
k návratu z volání metody. Služba MessageService zajistí, že zpráva dorazí ke všem
příjemcům.
K přijímání zpráv musí komponenta zaregistrovat do služby MessageService příjemce
zprávy. Příjemce je třída komponenty, která implementuje rozhraní MessageConsumer poskytované kontejnerem. Rozhraní obsahuje metodu recieveMessage(),
která je volána kontejnerem při odesílání zpráv a metodu getAcceptedMessage(),
ve které programátor specifikuje jména zpráv, které má příjemce dostávat. V hlavičce
manifestu Consume-Events pak komponenta specifikuje (uvedením jména a typu
zprávy), jaké zprávy je schopná přijímat.
Atributy
Posledním typem komunikace mezi komponentami jsou atributy. Atribut je libovolná
hodnota identifikovaná řetězcem - klíčem a může být buď poskytován (exportován), nebo
vyžadován (importován). Existuje stejný vztah mezi vyžadovanými a poskytovanými atributy jako mezi vyžadovanými a poskytovanými službami - kontejner nedovolí instalaci
komponenty, která importuje určitý atribut, pokud v systému neexistuje komponenta,
která daný atribut exportuje.
Rozdíl mezi zprávami a atributy je ten, že zprávy představují událost v čase, zatímco
atributy představují hodnoty čtené komponentami.
Atributy můžeme použít k dynamické konfiguraci aplikace. Za běhu systému je mohou
komponenty číst a podle toho reagovat. Atributy se v čase mohou měnit, takže by
komponenta neměla spoléhat na jediné přečtení atributu, ale měla by ho přečíst pokaždé,
když s ním chce pracovat.
V kontejneru je k dispozici seznam všech atributů a je přístupný komponentám
přes třídu BundleContext. Tato třída je předávána aktivátoru komponenty a pro
44
Komponentový model CoSi
práci s atributy nabízí metody setAttributeValue(String, Object) a getAttributeValue(String). Pouze komponenta, která exportuje atribut (uvádí ho
v hlavičce manifestu Provide-Attribute) má právo do atributu zapisovat metodou
setAttributeValue(). Číst atribut a získat jeho hodnotu metodou getAttributeValue() může jen komponenta, která atribut importuje (uvádí ho v hlavičce
manifestu Require-Attributes).
6.1.2 Specifikace komponenty - soubor manifest.mf
V této sekci popíšeme obecné principy hlaviček manifestu komponenty a více se zaměříme na nově přidané nebo upravené hlavičky. Úplný popis ostatních hlaviček manifestu
nalezneme v příloze 8.
Manifest komponenty se skládá z většího počtu hlaviček. Každá hlavička má svoje
jméno a hodnotu, oddělené dvojtečkou, a případně ještě atributy (nepovinné, není-li
uvedeno jinak). Příklad hlavičky:
Bundle - Name : E x t r a f u n c R e g i s t r y B u n d l e
„Bundle-Name“ je název hlavičky, „ExtrafuncRegistryBundle“ je pak hodnota hlavičky. V hodnotách hlaviček se často objevují definice verzí nebo intervalu verzí.
Syntax těchto definicí je přejatý z OSGi [20]. Zadefinujeme, jak se elementy verzí zapisují v manifestu:
Version
Verze se skládá z hlavního (major), vedlejšího (minor) a doplňujícího čísla (micro). Tato
čísla jsou oddělena tečkou. Volitelnou čtvrtou částí je popis verze (qualifier) - textový
doplněk verze oddělený uvedený za doplňujícím číslem a oddělený od něho tečkou.
Verze nesmí obsahovat žádné tzv. bílé znaky1 . Implicitní hodnota verze je 0.0.0. Pro
porovnání dvou verzí se používá standardní metoda Javy String.compareTo(),
takže například výraz „1.1.0.build-05“ < „1.1.0.build-3“ je vyhodnocený jako „true“.
Version Range
Version range (výraz version-range) představuje interval verzí. Může se vyskytnout například v hlavičkách vyžadovaných typů nebo služeb. Pokud je výraz version-range
zapsaný jako pouze jedna verze, je interpretovaný jako rozsah verzí [verze, ∞). Pokud
1 bílé
znaky jsou například mezera, tabulátor, atd.
45
Komponentový model CoSi
není rozsah specifikován, je použita implicitní hodnota 0, která je namapována na rozsah [0.0.0,∞). Element version-range musí být uzavřen do uvozovek, protože obsahuje
čárku, která by mohla kolidovat s ostatními definicemi.
Příklady (hodnota - význam):
[1.2.3 ,
[1.2.3 ,
(1.2.3 ,
(1.2.3 ,
1 . 2 .3
4.5.6)
4.5.6]
4.5.6)
4.5.6]
1.2.3
1.2.3
1.2.3
1.2.3
1.2.3
<= x < 4.5.6
<= x <= 4.5.6
< x < 4.5.6
< x <= 4.5.6
<= x
Následující text popisuje hlavičky, které se mohou vyskytnout v manifestu komponenty a jsou pozměněny od předchozí verze CoSi nebo jsou nově přidány. Hlavičky Control-Class, Bundle-Name, Bundle-Version, Cosi-Version, Bundle-Description,
Bundle-Provides, Bundle-Classpath, Generate-Events, Consume-Events, Provide-Attributes a Require-Attributes jsou podrobně popsány v příloze 8.
Require-Services
Definice vyžadovaných (importovaných) služeb. Je možné specifikovat další parametry,
které jsou použity při hledání vyžadované služby. Podporovány jsou atributy:
∙ versionrange - Rozmezí verzí, které musí mít exportované rozhraní. Implicitní
hodnota atributu je [0.0.0,∞). Syntax odpovídá výrazu version-range .
∙ name - Jméno exportující služby. Pokud je v systému více služeb implementujících
stejné rozhraní, jsou rozlišeny tímto jménem.
∙ bundle-name - Jméno exportující komponenty.
∙ bundle-provider - Jméno výrobce exportující komponenty.
∙ bundle-versionrange - Rozmezí verzí, které musí mít exportující komponenta, aby byla vybrána. Implicitní hodnota je [0.0.0,∞).
∙ autowire - Může nabývat hodnot „true“ nebo „false“. Určuje, zda se má automaticky injektovat objekt instance služby do předpřipravené proměnné uvnitř
aktivátoru komponenty (viz sekce 5.4.2). Pokud je atribut autowire přítomný,
musí být vyplněn také atribut name.
46
Komponentový model CoSi
Příklad definice:
Require - S e r v i c e s : cz . zcu . fav . kiv . c a l c o u t p u t .
C a l c O u t p u t P o r t s ; name =" c a l c o u t "; a u t o w i r e =" true " ,
cz . zcu . fav . kiv . u p d a t e s t a t e . U p d a t e S t a t e P o r t s
Provide-Services
Definice poskytovaných (exportovaných) služeb. Je možné specifikovat další parametry
pro poskytovanou službu. Tyto parametry ale nejsou povinné.
∙ version - Verze poskytované služby.
∙ name - Jméno poskytované služby. Pokud je specifikováno, nesmí kolidovat se
jménem jiné služby implementujícím stejné rozhraní. Jméno služby je nutné specifikovat, pokud chceme, aby bylo možné v komponentách importujících službu
použít dependency injection (viz sekce 5.4.2).
Framework přiřadí každé poskytované službě následující atributy (které se nesmí objevit
definici poskytované služby):
∙ bundle-name - Jméno exportující komponenty.
∙ bundle-version - Verze komponenty poskytující službu.
Příklad definice:
Provide - S e r v i c e s : cz . zcu . fav . kiv . t e s t b u n d l e 1 .
T e s t S e r v i c e ; v e r s i o n = 1 . 2 . 3 ; name =" T e s t S e r v i c e "
Provide-Types
Specifikuje typy exportované komponentou. Překrývá hlavičku Provide-Packages.
Definice exportovaných typů má stejný syntax jako definice exportovaných služeb.
Rozdílem je, že typy jsou třídy, které exportující komponenta chce zpřístupnit ostatním
komponentám, ale nemohou být interpretovány jako služby.
47
Komponentový model CoSi
Require-Types
Specifikuje typy importované komponentou. Překrývá hlavičku Require-Packages.
Definice importovaných typů má stejný syntax jako definice importovaných služeb.
Rozdílem je, že typy jsou třídy, které exportující komponenta chce zpřístupnit ostatním komponentám, ale nemohou být interpretovány jako služby. Pokud je komponenta
poskytující importovaný typ v systému, je tento typ přidán do class path importující
komponenty.
Provide-Packages
Specifikuje, jaké balíky tříd jsou exportovány komponentou. Znamená to, že všechny veřejné třídy obsažené v komponentě v balících definovaných v této hlavičce jsou zpřístupněny pro ostatní komponenty, pokud již nejsou zpřístupněny v hlavičkách ProvideTypes nebo Provide-Services.
Parametry, které mohou být specifikovány pro poskytované balíky:
version - Nepovinný parametr. Specifikuje verzi balíku poskytovaného komponentou.
Require-Packages
Specifikuje, jaké balíky jsou importovány komponentou (viz sekce 5.4.1). Sémantika
hlavičky je taková, že všechny veřejné třídy obsažené v uvedených balících jsou požadovány komponentou, pokud nejsou explicitně uvedeny v hlavičce Require-Types nebo
Require-Services. Tyto balíky musí být explicitně exportovány nějakou z komponent v systému.
Parametry, které mohou být specifikovány pro požadované balíky:
versionrange - Nepovinný parametr. Specifikuje rozmezí verzí importovaného
balíku. Implicitní hodnota je [0.0.0,∞).
Bundle-Extrafunc
Od verze 2 umožňuje CoSi specifikovat mimofunkční charakteristiky (EFP) pro komponentu nebo pro některou z jejích vlastností (viz sekce 5.1.1). Hlavička pro EFP platné
pro celou komponentu má následující syntax:
Bundle-ExtraFunc: <name>=<value>, ...
Pro EFP platné pro jednu vlastnost je použit syntax OSGi atributů:
<manifest-header>: <object>;extrafunc=(<name>=<value>, ...)
48
Komponentový model CoSi
Typ
boolean
integer
float
token
string
Formát hodnot
true|Y, false|N
32-bitový integer se
znaménkem
64-bitový IEEE
formát float
identifikátor s
pomlčkami a
podtržítky
textový řetězec v
dvojitých uvozovkách
Poznámka
Příklady hodnot
Y
-20471
je vyžadována
desetinná tečka
Viz 1.3.2 v [20]
0.57 25.3
embedded firstline
"That’s all,
folks“
Tabulka 6.1: Typy EFP - skalární
Typ
enum<type>
Formát hodnot
{ value [, value, . . . ]
}
Poznámka
Hodnoty musí být
stejného skalárního
typu.
map
{ identifier: value, . . . Hodnoty nemusí být
}
tejného skalárního
typu.
interval<type> (valmin ,[valmean ],valmax ] Hodnoty musí být
stejného typu. Je
použita OSGi notace
pro interval.
Příklady hodnot
{ start, stop,
unknown }
{ memory: low,
security: C2 }
(0.5,1.0] [small,
large, xxlarge]
Tabulka 6.2: Typy EFP - komplexní
Příklady:
Bundle - E x t r a F u n c : m e m o r y =32 , s e c u r i t y ={ basic ,
d i g e s t } , gc - model =" eager v3 " , p r e c i s i o n ={ n o r m a l
:"0.01" , high : " 0 . 0 0 0 1 " }
Export - S e r v i c e s : cz . zcu . fav . kiv . s e n s o r r e g i s t r y .
S e n s o r R e g i s t r y ; e x t r a f u n c =( s a m p l i n g r a t e <20 ,
precision = normal )
Import - S e r v i c e s : com . acme . a c t u a t o r . T e m p A c t u a t o r ;
e x t r a f u n c =( refresh < = 4 0 0 ) , com . other . comm .
49
Komponentový model CoSi
S e c u r e D a t a T r a n s f e r e r ; v e r s i o n ="[1.0 , 2.3) ";
e x t r a f u n c =( s e c u r i t y . method ,{ ssl , tls }) , perf .
d e l i v e r y _ t i m e <=10)
Typy EFP dělíme na skalární a komplexní. Všechny možné typy EFP jsou popsány
v tabulkách 6.1 a 6.2. Všechny tyto hlavičky a atributy předpokládají, že existuje registr
EFP (viz sekce 6.1.3).
Extrafunc-Catalog
Tato hlavička specifikuje umístění (URI) katalogu registu mimofunkčních charakteristik
(viz sekce 6.1.3). V současné podobě má hlavička pouze informační hodnotu. V další
verzi CoSi se však počítá s tím, že bude framework tento registr z daného umístění
stahovat.
Příklad:
ExtraFunc - C a t a l o g : http :// s e r v i c e s . kiv . zcu . cz /
cosi / e x t r a f u n c / v1 /
Další pravidla pro soubor manifest.mf
∙ Manifest může obsahovat i další definice neuvedené ve specifikaci. Tyto definice
jsou načteny, ale pouze jako řetězce bez dalšího významu (nejsou interpretovány
frameworkem). Hodnoty definic jsou přístupné v meta-datech balíku.
6.1.3 Registr mimofunkčních charakteristik
Pro podporu výzkumu v oblasti mimofunkčních charakteristik byl kontejner rozšířen
o jednoduchý registr, který obsahuje kompletní definice všech typů použitelných mimofunkčních charakteristik. Soubor registru používá následující syntax:
# c o m m e n t line
< prop - def > := < name > : < type > [; < constraint >]
< type > ::= see Bundle - E x t r a f u n c h e a d e r - EFP
t ypes
< c o nstraint > ::= < interval - constr > | < set - constr >
| < map - constr >
< interval - constr > ::= " <" < value > , < value > " >"
< set - constr > ::= "{" < value [ , ...] "}"
50
Komponentový model CoSi
< map - constr > ::= "{" < name > : < value > [ , ...] "}"
Registr je v CoSi přístupný prostřednictvím standardní služby ExtrafuncRegistryService (viz sekce 6.3.2). Implicitní registr EFP je umístěn v textovém souboru extrafuncregisty v balíku cz.zcu.fav.kiv.bdcontainer.extrafuncregistry
service.impl. Je možné použít i jiný soubor registru. Ve frameworku je pro to k dispozici metoda služby ExtrafuncRegistryService loadRegistryFromURL(URL).
Příklad souboru registru:
s e c u r i t y : enum ;{ ssl , tsl , none }
p r e c i s i o n : map ;{ low , normal , high }
r e s p o n s e : i n t e r v a l ;{ slow , average , fast }
s a m p l i n g r a t e : i n t e g e r ; <1 ,1000 >
gc - model : s t r i n g ; <" A " ," Z " >
gs - model : s t r i n g ;{" one " ," two " ," three "}
6.1.4 Distribuční forma komponenty
Komponenta je distribuována jako jediný JAR soubor obsahující vše potřebné pro její
běh. Framework nedovoluje komponentě využívat zdroje odjinud, než z JAR archivu
komponenty.
Archiv komponenty musí obsahovat adresář META-INF obsahující soubor manifest.mf s informacemi o komponentě. Také musí obsahovat další povinné adresáře
(viz obrázek 6.1; nepovinné adresáře jsou odděleny světlejší barvou). Kontejner kontroluje přítomnost těchto adresářů během instalace komponenty a nedovolí její zavedení
do systému, pokud nejsou adresáře nalezeny.
Archiv obsahuje následující adresáře:
∙ Adresář bin/ - povinný adresář, který obsahuje přeložený kód komponenty (popř.
zdrojové soubory jazyka Groovy určené k interpretování). Je implicitně zahrnut
do class path komponenty.
∙ Adresář lib/ - povinný adresář, který obsahuje knihovny potřebné ke správnému
běhu komponenty. Tyto knihovny mohou být uloženy jako JAR archivy. Knihovny,
které chce komponenta využívat, musí být uvedeny v class path komponenty.
∙ Adresář optional/ - nepovinný adresář. Může obsahovat v podstatě cokoliv.
51
Komponentový model CoSi
Obrázek 6.1: Struktura archivu komponenty
∙ Adresář src/ - nepovinný adresář. Obsahuje zdrojové soubory komponenty, pokud
je dodavatel chce poskytnout.
∙ Adresář doc/ - nepovinný adresář. Obsahuje dokumentaci komponenty.
6.1.5 Balík komponent
CoSi (od verze 2) umožňuje sdružovat komponenty do balíků komponent (assemblies).
Balíky jsou jednotkou instalace, odinstalace a nasazení. Sdružují více komponent, které
se mohou vzájemně doplňovat a poskytovat tak funkcionalitu jako celek. Usnadňuje také
zavedení komponent do systému.
Balík komponent obsahuje pouze komponenty a soubor manifestu.
6.1.6 Specifikace balíku komponent - soubor manifest.mf
V této sekci popíšeme manifest balíku komponent.
Soubor manifestu se skládá z hlaviček. Každá hlavička má své jméno a hodnotu,
oddělené dvojtečkou. Definice verzí u hodnot hlaviček mají stejný syntax jako definice
verzí u komponent (viz sekce 6.1.2). Následující text popisuje hlavičky, které se mohou
vyskytnout v manifestu balíku komponent.
52
Komponentový model CoSi
Assembly-Name
Specifikuje jméno balíku komponent.
Assembly-Version
Specifikuje verzi balíku komponent. Pokud dva balíky komponent obsahují různé verze
stejných komponent, musí se verze těchto balíků lišit.
Příklad:
Assembly - V e r s i o n : 1 . 2 . 3 . build -6
Assembly-Provider
Specifikuje poskytovatele balíku komponent.
Assembly-Description
Specifikuje krátký textový popis obsahu balíku.
Assembly-Bundles
Obsahuje jména komponent, které jsou obsažené v balíku komponent. Má následující
syntax:
Assembly - B u n d l e s : bundle - name , bundle - name , ...
Pro hodnoty této hlavičky platí následující pravidla:
∙ bundle-name je jméno komponenty odpovídající hodnotě hlavičky manifestu
komponenty Bundle-Name,
∙ bundle-name musí odkazovat na komponentu fyzicky přítomnou v balíku komponent. Pokud není komponenta přítomná v balíku, je tento záznam ignorován, i
když je balík se stejným názvem přítomen v systému.
∙ Komponenty uvnitř balíku jsou při instalaci vyhodnocovány v pořadí uvedeném v
této hlavičce.
Příklad:
53
Komponentový model CoSi
Assembly - B u n d l e s : S a v e C C M C o r e , U p d a t e S t a t e ,
C alcOutput , S p e e d C o n t r o l l e r , D i s t a n c e G e n e r a t o r ,
Printer , A C C A p p
Assembly-Wiring
V balíku komponent je možné explicitně nadefinovat provázání mezi službami komponent (atribut autowire u služeb). Toto provázání je definováno v hlavičce AssemblyWiring. Provázání existuje proto, aby bylo zajištěno správné navázání služby komponenty uvnitř balíku komponent na službu komponenty uvnitř balíku a ne na službu jiné
komponenty stejného jména, která je přítomná v kontejneru. Hlavička má následující
syntax:
Assembly - W i r i n g : bundle - name . e l e m e n t to bundle name . element , bundle - name . e l e m e n t to bundle name . element , ...
Platí následující pravidla:
∙ bundle-name odpovídá jménu komponenty a musí být zastoupeno také v hlavičce Assembly-Bundles
∙ element odpovídá jménu služby (atributu name u služby v sekci ProvidedServices nebo Required-Services)
∙ jedna strana provázání musí být exportovaná a druhá strana importovaná služba.
Není explicitně uvedeno pořadí, ve kterém by měly být služby uvedeny, ale je
doporučeno uvádět služby v pořadí „importovaná to exportovaná“.
∙ importovaná služba musí mít nastavený atribut autowired=“true“
Pokud některé z těchto pravidel není splněno, kontejner příslušné spojení nevytvoří.
6.1.7 Distribuční forma balíku komponent
Balík komponent je distribuován ve formě jednoho JAR archivu obsahujícího:
∙ Adresář META-INF se souborem manifest.mf, který obsahuje informace o balíku
komponent.
54
Životní cyklus komponenty a balíku komponent
∙ JAR archivy s komponentami přímo v kořenovém adresáři balíku.
Pokud není soubor manifestu kontejnerem nalezen, není balík komponent zaveden do
systému.
6.2 Životní cyklus komponenty a balíku komponent
Životní cyklus komponenty v CoSi vychází z životního cyklu komponenty v OSGi.
Je to proces od počátku existence komponenty v systému do jejího odstranění. Proces
začíná nainstalováním komponenty. Pokračuje ověřením jejích závislostí a korektnosti.
Tento proces se nazývá vyhodnocení komponenty. Po úspěšném vyhodnocení může být
komponenta spuštěna. Není-li jí dále potřeba, může být zastavena nebo odinstalována
ze systému. Komponenta také může být deaktivována - uvedena do stavu těsně po
nainstalování.
Rozeznáváme následující stavy (viz obrázek 6.2):
∙ INSTALLED - komponenta byla úspěšně nainstalována nebo deaktivována. Deaktivace se provádí například při odinstalaci balíku komponent ze systému nebo
pokud potřebujeme komponentu přesunout z aktivního stavu do stavu před vyhodnocením.
∙ RESOLVED - komponenta je vyhodnocena - všechny závislosti vyžadované komponentou jsou přítomny v systému. V tomto stavu se nachází komponenta, která
je zastavena nebo připravena na nastartování.
∙ STARTING - komponenta je startována. Byla vyvolána metoda start() rozhraní BundleControl a volání této metody nebylo ještě ukončeno.
∙ STARTED - komponenta byla úspěšně nastartována a běží.
∙ STOPPING - komponenta je zastavována. Byla vyvolána metoda stop() rozhraní BundleControl a volání této metody nebylo ještě ukončeno.
∙ UNINSTALLED - komponenta byla odinstalována ze systému. Tento stav je konečný - nemůže z něj být přesunuta do jiného stavu.
Pro balík komponent rozeznáváme pouze dva stavy (viz obrázek 6.3):
55
Životní cyklus komponenty a balíku komponent
Obrázek 6.2: Životní cyklus komponenty v CoSi
∙ INSTALLED - balík komponent byl nainstalován. Byla úspěšně vyvolána metoda installAssembly() rozhraní Assembly. To, že je balík komponent
ve stavu INSTALLED neznamená, že byly do systému úspěšně nainstalovány veškeré komponenty, které balík obsahuje. Znamená to pouze, že byl úspěšně načten
JAR soubor balíku aa přečten jeho manifest. To znamená, že balík je syntakticky
v pořádku a může následovat vyhodnocování jeho komponent.
∙ UNINSTALLED - v tomto stavu se může balík komponent nacházet, pokud
1. byl balík načten do systému, ale ještě nebyla vyvolána metoda installAssembly() rozhraní Assembly
2. volání této metody skončilo s chybou (nelze přečíst JAR soubor balíku)
3. byl balík komponent odinstalován ze systému. V případě odinstalování balíku
je stav UNINSTALLED konečný.
56
Životní cyklus komponenty a balíku komponent
Obrázek 6.3: Životní cyklus balíku komponent v CoSi
6.2.1 Proces vyhodnocení komponenty
Prvním krokem při instalaci komponenty je její vyhodnocení 2 . Vyhodnocení komponenty
je proces, ve kterém se pro jednotlivé importy (tedy požadované typy, atributy, služby a
zprávy) komponenty hledají odpovídající exportéři. Komponenty mohou na své importy
ukládat omezení (constraints) ve formě například specifické verze, jména služby nebo
přesného názvu poskytující komponenty. Pokud není v systému nalezena komponenta,
která exportuje odpovídající položku, není komponenta vyhodnocena a zůstává ve stavu
INSTALLED. Je možné se později pokusit o nové vyhodnocení komponenty, například
pokud do systému přidáme další komponenty. Komponenta musí být vyhodnocena před
spuštěním jakéhokoliv jiného kódu.
Kontejner během vyhodnocování kontroluje:
1. jestli je komponenta ve stavu INSTALLED nebo RESOLVED. Komponenta tedy
musí být korektně nainstalována, aby mohla být vyhodnocena. Již vyhodnocená
komponenta může být znovu vyhodnocena.
2. jestli se v kontejneru nacházejí poskytovatelé pro všechny importované služby. Během vyhodnocování je pouze zkontrolována přítomnost služeb (balíků) v systému,
nevytvářejí se žádné vazby na poskytovatele. V této části se zároveň se kontrolují
EFP navázané na služby. Pokud je nalezen exportér služby, ale daná služba nesplňuje požadavky na EFP, kontejner podle konfigurace buď zaloguje chybu a dále
pokračuje ve vyhodnocování, nebo zaloguje chybu a s vyhodnocováním skončí.
2v
angl. jazyce je vyhodnocení komponenty označováno jako bundle resolve
57
Životní cyklus komponenty a balíku komponent
3. jestli se v kontejneru nacházejí poskytovatelé pro všechny importované typy. Stejně
jako u služeb je během vyhodnocování pouze zkontrolována přítomnost typů v systému, nevytvářejí se žádné vazby na poskytovatele.
4. jestli se v kontejneru nacházejí poskytovatelé pro všechny importované balíky.
Stejně jako u služeb je během vyhodnocováni pouze zkontrolována přítomnost
balíků v systému, nevytvářejí se žádné vazby na poskytovatele.
5. jestli se v kontejneru nacházejí poskytovatelé pro všechny importované atributy.
Stejně jako u služeb je během vyhodnocování pouze zkontrolována přítomnost
atributů v systému, nevytvářejí se žádné vazby na poskytovatele.
6. jestli se v kontejneru nacházejí poskytovatelé pro všechny importované zprávy.
Stejně jako u služeb je během vyhodnocování pouze zkontrolována přítomnost
atributů v systému, nevytvářejí se žádné vazby na poskytovatele.
7. jestli jsou korektně exportovány poskytované atributy (jestli jsou komponentou
exportovány typy atributů). Toto pravidlo může být porušeno, pokud komponenta
typ atributu importuje. Také není nutné exportovat typy, které jsou součástí Boot
class path (viz sekce 6.4).
8. jestli jsou korektně exportovány poskytované zprávy. Pro typy zpráv platí stejná
pravidla jako pro typy atributů.
9. pokud byla komponenta před vyhodnocením ve stavu RESOLVED, tímto krokem
vyhodnocení končí. Pokud byly všechny předešlé kroky úspěšně vykonány, je
komponenta přesunuta do stavu RESOLVED. Pokud alespoň jeden z těchto kroků
selhal, komponenta se vrátí do stavu INSTALLED a kontejner se musí vrátit do
stavu, ve kterém byl před prvním (úspěšným) vyhodnocováním této komponenty.
Pokud byla komponenta ve stavu INSTALLED, pokračuje proces vyhodnocování
následujícími kroky:
10. Všechny zdroje komponenty (typy, služby, atributy nebo zprávy) jsou zaregistrovány do systému.
11. Komponenta je navázána na své poskytovatele. Na rozdíl od OSGi neexistuje
v CoSi k tomuto účely žádný speciální objekt (wire), takže navázání je možné
implementovat jako seznam exportů a importů.
12. Je vytvořena instance aktivátoru komponenty.
58
Životní cyklus komponenty a balíku komponent
Pokud jsou i tyto kroky úspěšné, je komponenta přesunuta do stavu RESOLVED a je
připravena ke spuštění. Během kontroly služeb, atributů, zpráv a typů musí být brány
v potaz omezení uložená na tyto vlastnosti, aby byla komponenta navázána na správné
poskytovatele.
6.2.2 Rozhraní komponenty a balíku komponent
CoSi definuje několik rozhraní úzce spjatých s komponentou, jejími vlastnostmi a s balíkem komponent. Jsou to rozhraní:
∙ Bundle - reprezentuje komponentu a poskytuje metody životního cyklu komponenty.
∙ BundleMetaData - poskytuje přístup k informacím v manifestu komponenty.
∙ ServiceReference - reprezentuje poskytovanou službu.
∙ ModuleClassLoader - obecné rozhraní pro class loader použitelný v CoSi
kontejneru.
∙ Assembly - reprezentuje balík komponent ve frameworku a poskytuje metody
životního cyklu balíku komponent.
∙ AssemblyMetaData - poskytuje přístup k informacím v manifestu balíku komponent.
Rozhraní ServiceReference a ModuleClassLoader se od první verze CoSi
nezměnila. Změny rozhraní Bundle a BundleMetaData jsou minimální. Rozhraní
Assembly a AssemblyMetaData jsou v CoSi nově od verze 2. V této části popíšeme pouze rozhraní Assembly, podrobný popis všech rozhraní nalezneme v dokumentaci zdrojových kódů na přiloženém CD a v [22].
Rozhraní Assembly
Objekt typu Assembly je abstrakcí balíku komponent uvnitř kontejneru. Každý balík
komponent má přidělený právě jeden objekt tohoto typu.
Definice rozhraní:
59
Životní cyklus komponenty a balíku komponent
p u b l i c c l a s s Assembly {
p u b l i c s t a t i c f i n a l i n t INSTALLED = 0 ;
p u b l i c s t a t i c f i n a l i n t UNINSTALLED = 1 ;
public boolean i n s t a l l A s s e m b l y ( ) ;
public boolean u n i n s t a l l A s s e m b l y ( ) ;
public void s t a r t A s s e m b l y ( ) ;
public boolean stopAssembly ( ) ;
public int getId ( ) ;
public void s e t I d ( i n t id ) ;
p u b l i c S t r i n g getName ( ) ;
public List < Integer > getBundleIDs ( ) ;
public boolean c a n E s t a b l i s h W i r e ( S t r i n g
serviceNameAttribute , S t r i n g serviceNameValue ) ;
public int g e t S t a t e ( ) ;
public boolean i s I n s t a l l e d ( ) ;
public AssemblyMetadata getAssemblyMetadata ( ) ;
}
Popis jednotlivých složek rozhraní:
Konstanty INSTALLED a UNINSTALLED představují stavy balíku komponent (viz
výše).
public boolean i n s t a l l A s s e m b l y ( ) ;
public boolean u n i n s t a l l A s s e m b l y ( ) ;
Tyto metody kontrolují životní cyklus balíku komponent.
public boolean stopAssembly ( ) ;
public void s t a r t A s s e m b l y ( ) ;
Pomocné metody pro nastartování a deaktivování všech komponent uvnitř balíku. Tyto
metody neovlivní životní cyklus balíku komponent.
public int g e t S t a t e ( ) ;
public boolean i s I n s t a l l e d ( ) ;
Metody pro zjištění stavu balíku komponent.
public int getId ( ) ;
public void s e t I d ( i n t id )
Vrátí (nastaví) jednoznačný identifikátor balíku komponent uvnitř kontejneru.
60
Kontejner
p u b l i c S t r i n g getName ( ) ;
Vrátí jméno archivu balíku komponent.
public List < Integer > getBundleIDs ( ) ;
Vrátí seznam identifikátorů komponent nainstalovaných v kontejneru patřících tomuto
balíku.
public boolean c a n E s t a b l i s h W i r e ( S t r i n g s e r v i c e N a m e A t t r i b u t e
, S t r i n g serviceNameValue ) ;
Vrátí true pokud je možné vytvořit spojení mezi dvěma službami uvedenými v manifestu balíku komponent v hlavičce Assembly-Wiring.
public AssemblyMetadata getAssemblyMetadata ( ) ;
Vrátí zpracovaná meta-data balíku komponent.
6.3 Kontejner
Kontejner je část CoSi zodpovědná za:
∙ korektní nahrávání komponent do systému, obstarávání jejich životního cyklu (viz
sekce 6.2)
∙ udržování registru služeb poskytovaných komponentami
∙ udržování seznamu a hodnot atributů poskytovaných komponentami
∙ poskytování informací o komponentách (například o jejich stavu, závislostech nebo
metadatech)
∙ poskytování služby pro ovládání životního cyklu komponent
∙ poskytování služby pro posílání a přijímání zpráv
∙ poskytování služby pro podporu EFP komponent a vlastností komponent
Kontejner je běhovým prostředím pro komponenty. Sám o sobě nemá žádnou funkčnost,
ale umožňuje komponentám interagovat a poskytovat funkčnost okolí.
Pokud komponenta A poskytuje typ, atribut nebo zprávu a v systému existuje komponenta B importující jeden z těchto elementů, musí být komponenta B nejdříve ukončena
a odinstalována, aby bylo možné odinstalovat komponentu A.
61
Kontejner
Tímto návrhovým omezením je zajištěno korektní běhové prostředí pro komponenty.
Na rozdíl od OSGi totiž CoSi negeneruje zprávy oznamující odinstalaci služeb ostatním
komponentám. Je zajištěno, že dokud komponenta běží, všechny vyžadované služby, na
které komponenta získala odkaz během svého běhu, jsou přítomné v systému, dokud
není na komponentě vyvolána metoda stop().
6.3.1 Rozhraní kontejneru
Ačkoliv jsou komponenty v CoSi považovány za černou skříňku (okolí nemá žádné informace o komponentě kromě toho, jaké položky exportuje), je nutné, aby mohly komponenty komunikovat s frameworkem a framework s komponentami. Tato funkcionalita
je zajištěna dvěma rozhraními kontejneru. Prvním rozhraním je BundleControl,
které musí být implementováno každou komponentou a je jím kontrolován životní cyklus komponenty. Druhým je rozhraní BundleContext. To je předáno každé instanci
komponenty a poskytuje základní informace o prostředí komponenty.
Rozhraní BundleControl
Rozhraní BundleControl musí být implementováno v jedné ze tříd každé komponenty, aby mohl kontejner komponentu spustit či zastavit. Během procesu vyhodnocení
komponenty kontejner vytvoří instanci třídy, která je uvedena v hlavičce manifestu komponenty Control-Class, a zkontroluje, zda třída korektně implementuje rozhraní
BundleControl. Pokud je na této instanci úspěšně vyvolána metoda start(), je
zajištěno, že metoda stop() bude vyvolána při zastavování komponenty na stejné
instanci třídy BundleControl.
Kontejner zajistí, že obě operace budou správně započaty a pokud nastane výjimka
během startování nebo zastavování komponenty, bude odchycena, aby nebyly ostatní
komponenty touto výjimkou ovlivněny. Kontejner zaloguje tyto výjimky, vrátí komponentu do stavu RESOLVED a odebere služby a atributy registrované komponentou ze
systému.
V metodě start() by komponenty měly získat odkazy na služby jiných komponent
nebo zaregistrovat své služby a atributy do systému. Metoda stop() je pak místem,
kde komponenta musí odregistrovat všechny své služby, atributy a zprávy.
Definici rozhraní BundleControl a podrobný popis metod rozhraní nalezneme
v javadoc dokumentaci zdrojového kódu.
62
Kontejner
Rozhraní BundleContext
Objekt kontextu komponenty slouží ke komunikaci komponenty s frameworkem, přístupu
k frameworku a k přístupu ke službám registrovaným uvnitř frameworku. Komponenty
registrují svoje služby a získávají služby jiných komponent právě přes toto rozhraní.
Kromě toho umožňuje rozhraní BundleContext:
∙ registraci a získávání služeb
∙ získávání metadat komponent
∙ používání standardního vstupu a výstupu poskytovaného frameworkem
∙ zapisovat a číst atributy
Instance rozhraní je komponentě předána v metodě start(BundleContext) rozhraní BundleControl. Ta stejná instance je pak předána komponentě asociované
s tímto kontextem v metodě stop(BundleContext). Kontext komponenty by měl
být používán pouze s komponentou, která je k němu asociována a neměl by být sdílený
mezi komponentami.
Instance kontextu je platná pouze během aktivního stavu komponenty (tzn. jen ve stavech STARTING, STARTED s STOPPING) a nemůže být použita, pokud je komponenta
ve stavu jiném. Pokud je komponenta zastavena a znovu spuštěna, je s ní asociována
nová instance kontextu.
Definici rozhraní BundleContext a podrobný popis metod rozhraní nalezneme
v javadoc dokumentaci zdrojového kódu.
6.3.2 Základní služby kontejneru
Kontejner poskytuje komponentám základní API ve formě následujících služeb:
∙ SystemService je služba používaná komponentami ke kontrole životních cyklů
jiných komponent a zjišťování informací o vnitřním stavu kontejneru.
∙ MessageService je služba, kterou mohou komponenty použít k zasílání a přijímání
zpráv.
∙ ExtrafuncRegistryService je služba poskytující možnost používat EFP v popisu
komponent.
63
Kontejner
Tyto tři služby jsou vždy dostupné všem balíkům v kontejneru a jsou to první tři služby,
které kontejner ihned po svém startu instaluje do systému. Služby jsou v kontejneru
dostupné v podobě komponent "systembundle", "messagebundle" a "extrafuncregistrybundle". Tyto komponenty nemohou být zastaveny ostatními komponentami.
SystemService
Framework musí obsahovat implementaci, která registruje službu SystemService hned po
startu frameworku. Služba umožňuje komponentám základní přístup k systému, instalaci
a kontrolu životního cyklu ostatních komponent nebo získávat informace o závislostech
komponent.
Instance této služby je vždy přítomná v systému jako komponenta s id 0, je nastartována přede všemi ostatními komponentami a její hlavní funkcionalitou je delegace
požadavků na služby jádra frameworku. Detailní popis metod služby se nachází v javadoc dokumentaci zdrojových kódů kontejneru.
MessageService
Framework musí obsahovat komponentu registrující MessageService při svém startu.
Tato komponenta dostane id 1 a musí být nainstalována do systému hned po instalaci
SystemService (před instalací ostatních komponent).
Když chce komponenta vytvářet událost (posílat zprávu), implementuje v jedné ze
svých tříd abstraktní třídu Message. Tento objekt je pak odeslán službě MessageService
metodou sendMessage() nebo postMessage() a doručen všem komponentám
schopným přijmout danou událost.
Pokud chce komponenta zachytit událost (přijmout zprávu), musí implementovat rozhraní MessageConsumer a registrovat tuto implementaci ve službě MessageService
metodou registerMessageConsumer(). Služba pak doručí událost tomuto objektu.
Služba kontroluje, zda může komponenta přijmout či odeslat zprávu. Informace uvedené ve zprávě musí odpovídat informacím v manifestu komponent účastnících se odesílání nebo příjmu zpráv. Před odesláním zprávy je také kontrolováno, zda je odesílající
komponenta v aktivním stavu. Pokud není, musí služba ze systému odstranit všechny
implementace rozhraní MessageConsumer zaregistrované odesílající komponentou a
zpráva není doručena příjemcům. Pokud totiž nastane při ukončování komponenty výjimka a kvůli tomu se korektně neodregistrují příjemci zpráv generovaných ukončovanou
64
Kontejner
komponentou, musí to služba MessageService rozpoznat a musí odregistrovat všechny
tyto příjemce.
Detailní popis metod služby se nachází v [22] a v javadoc dokumentaci zdrojových
kódů kontejneru.
ExtrafuncRegistryService
Framework musí obsahovat komponentu registrující ExtrafuncRegistrySerice při svém
startu. Tato komponenta dostane od kontejneru id 2 a musí být nainstalována po komponentě MessageService a před ostatními komponentami.
Tato služba poskytuje funkcionalitu spojenou s EFP. Poskytuje možnost kontrolovat validitu EFP komponenty nebo služby komponenty oproti registru EFP a možnost
ověřit, zda EFP jedné komponenty (služby) poskytují všechny EFP požadované jinou
komponentou (službou).
Rozhraní služby je definované následovně:
public interface ExtrafuncRegistryService {
/ * * E v a l u a t e s u b s t i t u t a b i l i t y o f two p r o p e r t i e s . * /
public boolean checkExtraFuncMatch ( ExtraFunc lhsExtraFunc
, ExtraFunc rhsExtraFunc ) ;
/* * Verify property correctness . */
public boolean checkExtraFuncValid ( ExtraFunc e x t r a f u n c ) ;
/ * * I n i t i a l i z e r e g i s t r y from a d e f i n i t i o n f i l e . * /
p u b l i c v o i d l o a d R e g i s t r y F r o m U R L (URL u r l ) throws E x c e p t i o n
;
}
Popis jednotlivých metod:
public boolean checkExtraFuncMatch ( ExtraFunc lhsExtraFunc ,
ExtraFunc rhsExtraFunc ) ;
Vrací true, pokud lhsExtraFunc (vyžadované EFP) jsou podmnožinou rhsExtraFunc
(poskytované EFP). To znamená, že poskytované EFP jedné komponenty (služby) vyhovují požadovaným EFP jiné komponenty (služby). Implementuje proces porovnávání
mimofunkčních charakteristik (viz sekce 5.2.5).
public boolean checkExtraFuncValid ( ExtraFunc e x t r a f u n c ) ;
65
Class loading architektura
Zkontroluje validitu EFP komponenty (služby) oproti registru EFP. Například kontroluje, zda mají EFP správné typy definované v registru.
p u b l i c v o i d l o a d R e g i s t r y F r o m U R L (URL u r l ) throws E x c e p t i o n ;
Načte registr EFP (viz sekce 6.1.3) z URL. Používá se v případě, kdy implicitní registr
EFP nevyhovuje požadavkům aplikace.
6.4 Class loading architektura
Architektura nahrávání tříd v CoSi je zjednodušenou verzí této architektury v OSGi.
Všechny komponenty jsou instalovány a sdílí jeden virtuální stoj (VM). Uvnitř tohoto
vituálního stroje mohou komponenty skrývat své balíky a třídy před ostatními nebo
je naopak sdílet. Klíčovým mechanismem při skrývání a sdílení balíků je Java class
loader, který načítá třídy z podmnožiny prostoru balíků za použití předem definovaných
pravidel. CoSi framework musí implementovat speciální class loader řídící se pravidly
popsanými níže.
Každá komponenta má vlastní class loader, který se stará o nahrávání zdrojů. Aby
mohly komponenty mezi sebou sdílet zdroje, je potřeba vytvořit síť vzájemně propojených class loaderů poskytujících si zdroje podle jasných pravidel.
Class loader komponenty může nahrávat zdroje z následujících lokací:
∙ Boot class path - Class path dostupná pro všechny komponenty bez rozdílu. Obsahuje základní balíky potřebné k běhu programů napsaných v Javě nebo Groovy.
Je důležité, aby tyto balíky byly poskytovány pouze frameworkem. Komponenta
může předpokládat, že tyto zdroje jsou jí dostupné a nesmí je přidávat do své
class path.
∙ Framework class path - Class path poskytovaná frameworkem obsahující základní
množinu rozhraní a typů potřebných k vytvoření komponenty. Tyto typy a rozhraní
jsou automaticky přidány do class path komponenty.
∙ Bundle class path - Komponenty mohou definovat vlastní class path v manifestu
komponenty. Tato class path může odkazovat pouze na zdroje uvnitř komponenty
a je platná pouze pro danou komponentu.
Prostor tříd (class space) jsou všechny třídy dostupné z class loaderu dané komponenty.
Pro komponentu tedy prostor tříd tvoří:
66
Rozdíly proti ostatním specifikacím
∙ Rodičovský class loader (obyčejně třídy z boot class path, framework class path)
∙ Importované balíky a typy
∙ Class path komponenty
Prostor tříd jednoho balíku musí být konzistentní - nesmí obsahovat dvě třídy se stejným
plně kvalifikovaným jménem.
6.5 Rozdíly proti ostatním specifikacím
V této sekci popíšeme rozdíly proti dvěma existujícím specifikacím CoSi [6, 22].
Proti CoSi verze 1 [22] specifikace v této diplomové práci obsahuje:
∙ Možnost specifikovat EFP pro komponenty a jejich vlastnosti
∙ Balíky komponent
∙ Změněný meta-model CoSi (doplněný o balíky komponent a EFP)
∙ Podporu specifikace poskytovaných (vyžadovaných) balíků
∙ Upravený životní cyklus
∙ Upravený proces vyhodnocování komponenty
Technická zpráva [6] „The CoSi Component Model“ specifikuje cílový stav budoucí podoby CoSi, a z velké části vychází z rozšíření implementovaných v této diplomové práci.
Specifikace CoSi obsažená ve zprávě je však upravena s ohledem na další výzkum na
katedře a implementace těchto rozšíření je mimo rozsah diplomové práce. Tato technická
zpráva navíc oproti rozšířením implementovaným v diplomové práci specifikuje:
∙ Zprávy o událostech životního cyklu – specifikace kontejneru je doplněna o možnost zasílání zpráv o stavu životního cyklu komponent
∙ Doplněný životní cyklus komponenty – životní cyklus komponenty byl doplněný
o stav UPDATING
∙ Adresář imports – specifikace ve zprávě předepisuje adresář imports/, ve kterém se uchovávají třídy importované komponentou
67
Rozdíly proti ostatním specifikacím
∙ Jinou sémantiku hlavičky Extrafunc-Catalog – tato hlavička specifikuje umístění
katalogu registru EFP. V technické zprávě je přítomnost hlavičky podmínkou pro
práci s EFP – pokud není přítomná, jsou EFP zahozeny.
Technická zpráva naopak nespecifikuje podporu balíků komponent.
68
7 Implementace změn
Součástí této práce je implementace změn do existujícího kontejneru specifikace CoSi.
V této kapitole jsou popsány změny v architektuře kontejneru provedené v rámci práce,
doplňková služba pro mimofunkční charakteristiky a dva ukázkové scénáře, na kterých
je ověřena funkčnost implementovaných změn.
Tato implementace vychází z návrhu změn specifikace, popsaných v kapitolách 5 a 6.
Proto se tato kapitola podrobněji nevěnuje implementačním detailům jednotlivých tříd.
7.1 Jádro kontejneru
Jádro kontejneru bylo od první verze CoSi pozměněno. Byla přidána podpora balíků
komponent, dependency injection a podpora mimofunkčních charakteristik. Mechanismus class loaderů byl upraven pro podporu nahrávání komponent z URL a nahrávání
knihoven z JAR souborů až do druhé úrovně. Také byla přidána možnost specifikovat
exportované nebo importované balíky v popisu komponenty. Kromě toho byly provedeny drobné změny v implementaci, které ale nemají větší dopad na architekturu ani
funkčnost, proto zde nebudou popsány.
7.1.1 Architektura jádra kontejneru
Jádro kontejneru se skládá z hlavních tříd, které zajišťují funkčnost kontejneru a z vedlejších, které zajišťují podporu tříd hlavních. Vedlejší třídy jsou z hlediska architektury
nezajímavé, proto zde budou popsány pouze ty hlavní. Jedná se o třídy:
∙ BDContainer – představuje samotný kontejner
∙ DeployableManager – obsahuje seznam nainstalovaných komponent a balíků
komponent
69
Jádro kontejneru
∙ ApplicationContext – obsahuje informace o nainstalovaných komponentách, jejich službách, zprávách, atd. Dále obsahuje registr služeb a metody pro
práci s ním.
∙ BundleMetadata, AssemblyMetadata – obsahuje všechna meta-data komponenty (balíku komponent), včetně EFP.
Architektura jádra je vyobrazena na obrázku 7.1. Třídy v levém slouci představují nově
přidané do jádra CoSi, v prostředním sloupci jsou třídy, ve kterých byla provedena
změna a poslední skupina tříd (v pravém sloupci) jsou třídy původní implementace. Jak
je vidět, změny v implementaci jsou rozprostřeny přes celé jádro kontejneru.
BDContainer
Jedná se o hlavní třídu, reprezentující samotný kontejner. Nachází se v balíčku cz.zcu.
fav.kiv.bdcontainer a je zodpovědná za start, zastavení, inicializaci a konfiguraci
kontejneru (metodami start() a stop()) a za nainstalovnání a spuštění základních
systémových komponent (metoda processSystemBundles()).
Navíc oproti specifikaci umožňuje tato implementace CoSi specifikovat konfigurační
soubor kontejneru (deploy.config), ve kterém se nachází seznam komponent a balíků komponent, které mají být při startu kontejneru automaticky nainstalovány a spuštěny. Implementace také definuje konfigurační soubor cosi.config, který obsahuje
konfiguraci základních proměnných kontejneru jako je například jeho verze, chování při
vyhodnocování EFP, cesta k souboru deploy.config nebo adresář, ze kterého má
kontejner nahrávat komponenty.
DeployableManager
Tato třída přebírá funci třídy BundleManager z předchozí verze CoSi a doplňuje ji
o podporu balíků komponent. Obsahuje seznam nainstalovaných komponent reprezenovaných instancemi třídy BundleImpl implementující rozhraní Bundle a seznam
nainstalovaných balíků komponent, reprezentovaných instancemi třídy AssemblyImpl
implementující rozhraní Assembly. Třída poskytuje metody na práci s životním cyklem komponent a balíků komponent.
70
Jádro kontejneru
Obrázek 7.1: Architektura jádra kontejneru
71
Jádro kontejneru
ApplicationContext
Třída představuje dynamický pohled na kontejner. Obsahuje informace o poskytovaných
a vyžadovaných balících, typech, službách, atributech a zprávách jednotlivých nainstalovaných (běžících) komponent. Dále obsahuje metody pro usnadnění vyhledávání v těchto
informacích a registr služeb a atributy komponent.
Registr služeb je přístupný komponentě přes objekt typu BundleContext. Komponenty přes tento objekt registrují instanci služby, která je spolu s jejím popisem (instance
třídy ServiceReferenceImpl) uložena ve tříde ApplicationContext.
Proti CoSi verze 1 byla tato třída doplněna o podporu poskytovaných a vyžadovaných (java) balíků. Podrobný popis metod a proměnných třídy je k dispozici v javadoc
dokumentaci zdrojového kódu na přiloženém CD.
GClassLoader
Důležitou součástí implementace kontejneru CoSi je implementace class loaderu (viz
sekce 6.4), který je schopný pracovat se soubory napsanými jak v jazyce Java, tak
v jazyce Groovy. Specifikace CoSi předepisuje, aby takový class loader implementovat
rozhraní ModuleClassLoader. V této implementaci CoSi je rozhraní implementováno třídou GClassLoader v balíčku bdcontainer.moduleclassloader.
Do CoSi přibyla možnost distribuovat komponenty ve formě balíkudruh komponent.
Protože balík komponent je fyzicky reprezentován JAR archivem, který obsahuje JAR
archivy komponent, bylo nutné změnit implementaci třídy GClassLoader. Původní
implementace class loaderu měla možnost odkazovat se na JAR archivy uvnitř JAR
kořenového JAR archivu.
To ale pro implementaci balíků komponent nastačilo, protože by nebylo možné odkazovat na JAR archivy knihoven uvnitř komponent. Proto musela být do implementace
class loaderu přidána podpora pro odkazování na JAR archivy ve druhé úrovni zanoření
(na JAR archivy knihoven uvnitř archivu komponent, které jsou uvnitř archivu balíku
komponent).
Implementační detaily a podrobný popis nalezneme v javadoc dokumentaci k výše
uvedenému balíčku a také přímo ve zdrojovém kódu.
72
Implementace služeb
7.2 Implementace služeb
7.2.1 Služba ExtrafuncRegistryService
Služba pro podporu mimofunkčních charakteristik (viz sekce 6.3.2) je do kontejneru
nainstalována jako třetí v pořadí (v metodě processSystemBundles() třídy BDContainer), hned po dokončení instalace služby MessageService. Systémová
komponenta obsahující tuto službu je nainstalována do kontejneru s identifikačním číslem 2.
Kód implementující službu se nachází v distribučním archivu kontejneru v balíku
cz.zcu.fav.kiv.bdcontainer.extrafuncregistryservice. Podbalíček
impl obsahuje aktivátor komponenty (Activator), implementaci služby a implicitní
registr mimofunkčních charakteristik (soubor extrafuncregistry). V pod-balíčku
manifest se nachází manifest této komponenty.
Na rozdíl od ostatních systémových služeb, které pouze delegují volání do kontejneru, služba ExtrafuncRegistryService přímo implementuje poskytovanou
funkčnost. Při startu služby se načte implicitní registr mimofunkčních charakteristik ze
souboru extrafuncregistry a zkontroluje se validita všech položek, které obsahuje. Pokud implicitní registr pod danou aplikaci nevyhovuje, je možné ho metodou
loadRegistryFromURL přepsat. Funkcionalita této služby je podrobněji popsána
ve specifikaci CoSi v sekci 6.3.2.
Metoda checkExtraFuncMatch je použita také v jádře kontejneru při vyhodnocování komponenty. Změnou hodnoty EXTRAFUNC_ERROR_BEHAVIOUR v konfiguračním souboru cosi.config lze ovlivnit, jak se bude kontejner chovat při vyhodnocování komponenty (viz sekce 6.2.1) v závistlosti na návratové hodnotě této metody.
Jsou možné dvě hodnoty této konstanty:
∙ log - V případě, že metoda vrátí "false", zobrazí kontejner (zaloguje) chybovou
hlášku a pokračuje ve vyhodnocování.
∙ stop - V případě, že metoda vrátí "false", zobrazí kontejner chybovou hlášku a
ukončí vyhodnocování právě vyhodnocované komponenty s chybou.
7.2.2 Služba SimpleShell
Tato služba existuje v CoSi již od verze 1. Jedná se o základní službu pro interakci s kontejnerem, implementovanou komponentou simpleshell.jar. K interakci slouží jednoduchý
73
Implementace služeb
příkazový řádek (shell).
Standardní příkazy zahrnují ovládání životního cyklu komponent a zjišťování informací
o stavu kontejneru a systému. Kromě toho poskytuje komponenta službu pro registraci
nových příkazů. Komponenty v systému tak mohou službu použít pro implementaci
jednoduchého uživatelského rozhraní. Služba je podrobně popsána v [22].
Od původní verze byly upraveny následující příkazy:
∙ interfaces – nově výpis poskytovaných a vyžadovaných služeb zobrazuje také
hodnotu atributu name a autowire
∙ ps – vypíše všechny komponenty a nově také balíky komponent v systému
Také byly přidány nové příkazy:
∙ extrafunc <id> [-r|-p] – vytiskne na obrazovku vyžadované (–r) nebo
poskytované (–p) EFP služeb komponenty <id>
∙ astart <id>, astop <id> – spustí nebo zastaví (pokud je to možné) všechny
komponenty obsažené v balíku komponent <id>
∙ ainstall <id>, auninstall <id> – nainstaluje/odinstaluje balík komponent <id> ze systému. Při odinstalaci se pokouší o zastavení a odinstalování
všech komponent obsažených v balíku.
∙ aheaders <id> – vytiskne hlavičky obsažené v manifestu balíku komponent
<id>
∙ abundles <id> – vytiskne názvy a id komponent obsažených v balíku komponent <id>
∙ deactivate <id> – uvede komponentu <id> do stavu INSTALLED
Implementace služby se nachází v balíku cz.zcu.fav.simpleshell. Služba je
kompletně napsána v Groovy.
74
Ukázkové scénáře
7.3 Ukázkové scénáře
7.3.1 Ukázkový scénář - meteorologická stanice
Tento ukázkový scénář má za úkol otestovat použití mimofunkčních charakteristik v popisu služeb komponent. Jako základ použijeme příklad uvedený v sekci 2.2.4. Jedná se
o jednoduchou meteorologickou stanici, zastoupenou komponentami (viz obrázek 2.3):
∙ SensorRegistry - registr meteorologických senzorů. Senzory se registrují do SensorRegistry, aby mohly být použity v meteorologické stanici. Komponenta obsahuje služby SensorRegistry a SensorData v balíku cz.zcu.fav.kiv.sensorregistry.
∙ MeasuringStation - samotná stanice. Čte údaje ze senzorů registrovaných do
SensorRegistry (přes službu SensorData) a registruje nové příkazy do shellu na
spuštění tohoto příkladu.
∙ WindSpeedSensor - senzor poskytující údaje o rychlostech větru. Tyto údaje jsou
pouze náhodně generovaná čísla.
∙ TemperatureSensor - senzor poskytující údaje o teplotě. Tyto údaje jsou pouze
náhodně generovaná čísla.
WindSpeedSensor a TemperatureSensor jsou zástupci senzorů. Senzory se registrují do
registru senzorů (SensorRegistry) a může jich být libovolné množství. V tomto příkladu
jsou použity dva senzory WindSpeedSensor a dva senzory TemperatureSensor.
Služba SensorRegistry má v manifestu komponenty SensorRegistry následující definici:
Provide - S e r v i c e s : cz . zcu . fav . kiv . s e n s o r r e g i s t r y .
S e n s o r R e g i s t r y ; name =" r e g i s t r y "; e x t r a f u n c =(
s a m p l i n g r a t e = <10;30 > , s e n s o r t y p e ={ windspeed ,
t e m p e r a t u r e })
Popis mimofunkčních charakteristik:
∙ samplingrate - podporované rychlosti vzorkování senzorů
∙ sensortype - typy senzorů, které se mohou registrovat do registru senzorů
75
Ukázkové scénáře
Tyto mimofunkční charakteristiky jsou samozřejmě smyšlené a nemají žádný vliv na
funkci komponent, ale pro účel úlohy dostačují. Všechny senzory importují službu SensorRegistry a mají v hlavičce Require-Services u služby uvedené požadované
mimofunční charakteristiky. Vždy jeden z dvojice senzorů stejného typu má „správné“
hodnoty (požaduje mimofunkční charakteristiky, které služba SensorRegistry poskytuje)
a jeden „špatné“.
Podle nastavení kontejneru (viz 7.2.1) buď selže, nebo neselže vyhodnocení komponent, které mají „špatné“ požadované mimofunkční charakteristiky. Po nastartování
všech komponent tak registr senzorů obsahuje 2 (4) senzory a je možné příklad spustit.
O spuštění příkladu se stará komponenta MeasuringStation, která registruje do shellu
příkaz measure. Tento příkaz může být
1. bez parametrů - pro všechny senzory vypíše na standardní výstup hodnoty jimi
generované
2. s parametrem min|max|avg - pro všechny senzory vypíše na standardní výstup
kontejneru minimální (maximální, průměrnou) hodnotu z hodnot vygenerovaných
daným senzorem
Příklad výstupu:
> m e a s u r e avg
T e m p e r a t u r e -0 ,6 d e g r e e C e l s i u s
W i n d S p e e d 26 ,1 m / s
7.3.2 Ukázkový scénář - SaveCCM/CoSi transformace
Tento ukázkový scénář se zaměřuje na použití balíku komponent. Vychází z projektu
Transformation from SaveCCM to CoSi [17], který prozkoumává možnost transformace
mezi komponentovým modelem SaveCCM (viz sekce 3.4) a CoSi. Výsledkem tohoto
projektu je skupina komponent, které představují jádro SaveCCM v CoSi a návod
jak konstruovat systém propojených CoSi komponent odpovídající systému navrženému
v SaveCCM. Součástí návodu je popis, jak se architektonické elementy SaveCCM mapují
na architektonické elementy CoSi.
Není úkolem práce popsat tuto transformaci. Pouze uvedeme základní prvky mapování
architektonických prvků komponentových modelů, aby bylo možné lépe pochopit tento
ukázkový scénář. V následujícím mapování je na prvním místě vždy prvek z SaveCCM
a následně jeho ekvivalent v CoSi.
76
Ukázkové scénáře
∙ datový port se mapuje na atribut komponenty s definovaným typem a trigger port
na služby komponenty s definovaným jménem a typem
∙ kombinovaný port se mapuje jako dvojice datového a trigger portu se stejným
jménem
∙ konexe se nemapuje na architektonický element CoSi - je reprezentova objektem
vytvářeným za běhu
∙ komponenta se mapuje na CoSi komponentu s předem definovaným chováním a
množinou rozhraní
∙ quality attributes komponenty jsou reprezentovány EFP komponenty (viz hlavička
Bundle-Extrafunc v sekci 6.1.2)
∙ hodiny a zpoždění jsou reprezentovány knihovními třídami
∙ přepínač je mapován na CoSi komponentu s předem definovaným chováním a
množinou rozhraní
∙ assembly se také mapuje na CoSi komponentu s předem definovaným chováním
V době, kdy vznikala transformace, ještě nebyl komponentový model CoSi rozšířen
o balíky komponent. Proto je mapování neobsahuje.
Představme si hypotetický systém navržený v SaveCCM – adaptivní tempomat (The
Adaptive Cruise Controller - dále jen ACC). Jedná se o systém propojených komponent,
který má za úkol z údajů o vzdálenosti automobilu od automobilu před ním a z aktuální rychlosti vypočítat rychlost, kterou by měl automobil jet, aby dodržel bezpečnou
vzdálenost od vpředu jedoucího automobilu. Rychlost se počítá a upravuje několikrát za
sekundu tak, aby bylo možné předejít srážce. Tento systém namodelovaný v SaveCCM
(obrázek 7.2) předeveme do CoSi.
Transformovaný systém obsahuje následující CoSi komponenty:
∙ Speed Controller – reprezentace SaveCCM assembly obsahující komponenty Calc
Output a Update State
– Calc Output – simuluje výpočet výsledné rychlosti
– Update State – uchovává stav poslední rychlosti, aby bylo možné zjistit, zda
má automobil zpomalit nebo zrychlit
77
Ukázkové scénáře
∙ Distance Generator – simuluje prostředí (senzory automobilu) generováním náhodných dat na výstupech (portech)
∙ Clock1 – hodiny – generují trigger signály na výstupu
∙ Printer – komponenta pouze tiskne na obrazovku výstup z komponenty Speed
Controller
∙ ACCApp – komponenta zapouzdřující aplikaci. Jedná se o top-level SaveCCM
assembly. Registruje do shellu CoSi příkazy pro otestování aplikace (viz dále).
Má stejné jméno jako výsledný balík komponent.
Dále obsahuje pomocnou komponentu SaveCCMCore nutnou pro nasazení a spuštění
systému.
Pro otestování funkčnosti balíku komponent byly všechny komponenty ACC uloženy do jednoho CoSi assembly s názvem ACCApp a nasazeny do systému. Import
správných služeb trigger portů importujícími komponentami byl zajištěn atributem autowire. Například komponenta Calc Output exportuje trigger port in1 a komponenta
Speed Controller ho importuje. V manifestu balíku komponent ACCApp se proto objeví
následující konstrukce:
Assembly - W i r i n g : C a l c O u t p u t . in1 to
S p e e d C o n t r o l l e r . in1
Tento systém komponent registruje do shellu CoSi dva příkazy:
1. accapp start <ms> – Spustí hodiny Clock1, které začnou generovat trigger
signály.
2. accapp createXML <filename> – vytvoří SaveCCM XML deskriptor systému (viz [17]).
Příklad výstupu příkazu accapp start 500:
P r i n t e r c o m p o n e n t - port v a l u e s :
controlIn :
Max . speed : 50
C u r r e n t speed : 46
Distance : 4
U p d a t e State : 0
printerIn :
s p e e d i n g up
V rámci projektu [17] bylo ověřeno, že výsledný systém funguje a generuje správné
SaveCCM XML. Správně se naváží všechny závislosti a nainstalují se komponenty do
systému. Funguje i odinstalování balíku komponent ze systému.
78
Ukázkové scénáře
Obrázek 7.2: ACC systém v SaveCCM
79
8 Závěr
Hlavním cílem této diplomové práce bylo navrhnout a implementovat rozšíření komponentového modelu CoSi o mimofunkční charakteristiky a balíky komponent.
Při realizaci práce jsem nastudoval obecné principy komponentových technologií a
zjistil jsem, co jsou to softwarové komponenty, k čemu slouží a jak se popisují jejich
vlastnosti. Prozkoumal a vyhodnotil jsem několik obecně přijímaných řešení pro popis
mimofunkčních charakteristik komponent. Největší výzvou pro mě bylo proniknutí do
světa komponentových technologií, o kterých jsem měl před realizací práce jen velmi
omezené znalosti.
Po seznámení se s existujícími komponentovými modely (OSGi, SaveCCM, EJB) a
důkladné analýze specifikace a implementace experimentálního komponentového modelu CoSi jsem navrhl jeho rozšíření o pokročilé aspekty komponentových modelů.
Model jsem rozšířil o možnost specifikace mimofunkčních charakteristik komponent a
o balíky komponent.
Daná rozšíření jsem implementoval a ověřil jejich funkčnost na příkladových scénářích.
Jsem přesvědčen, že rozšíření komponentového modelu CoSi poskytne další vědecké
příležitosti v oblasti výzkumu nahraditelnosti komponent a popisu mimofunkčních charakteristik komponent.
Do budoucna je možné rozšířit popis mimofunkčních charakteristik komponent o odvozené charakteristiky (podle [12, 16]). Ty by byly vyjádřeny jednoduchým jazykem
a automaticky počítány ze základních. Dalším možným rozšířením je změna přístupu
k balíku komponent. Mohli bychom balík komponent považovat také za komponentu a
tím transformovat CoSi na plně hierarchický komponentový model.
80
Seznam zkratek
API
Application Programming Interface
ACC
The Adaptive Cruise Contoller
CoSi
Components Simplified
CBD
Component Based Development
CBSE
Component Based Software Engineering
CQM
Component Quality Model
EJB
Enterprise JavaBeans
EFP
Extra-Functional Properties.
IDL
Interface Definition Language
IoC
Inversion of Control
LDAP
Lightweight Directory Access Protocol
JAR
Java Archive soubor
OSGi
Open Services Gateway initiative
QoS
Quality of Service
SaveCCM The SaveComp Component Model
UML
Unified Modelling Language
XML
eXtensible Markup Language
81
Literatura
[1] ALUR, R. – DILL, D. L. A Theory of Timed Automata. Theoretical Computer
Science. 1994, 126, s. 183–235.
[2] ALVARO, A. – ALMEIDA, E. – MEIRA, S. A software component quality model:
A preliminary evaluation. In Proceedings of the 32nd EUROMICRO Conference on
Software Engineering and Advanced Applications (EUROMICRO?06), s. 28–37,
2006.
[3] BACHMANN, F. et al. Volume II: Technical concepts of component-based software
engineering. Carnegie Mellon University, Software Engineering Institute, 2000.
[4] BASS, L. – CLEMENTS, P. – KAZMAN, R. Software architecture in practice.
Addison-Wesley Professional, 2003.
[5] BEUGNARD, A. et al. Making components contract aware. Computer. 1999, 32,
7, s. 38–45.
[6] BRADA, P. – LISKA, V. – WAJTR, B. The CoSi Component Model. Technical report, University of West Bohemia Department of Computer Science and
Engineering, July 2008.
[7] BUREŠ, T. – HNTYNKAL, P. – PLÁŠIL, F. SOFA 2.0: Balancing advanced
features in a hierarchical component model. In Proc. of SERA, 2006.
[8] CRNKOVIC, I. – LARSON, M. Building reliable component-based software systems. Artech House, 2002.
[9] DESMOND FRANCIS, D. – WILLS, A. Objects, components, and frameworks
with UML: the catalysis approach. Addison-Wesley, 1999.
[10] EJB Specification. Version 3.0. Sun Microsystems. 2006.
82
Literatura
[11] FOWLER, M. Inversion of Control Containers and the Dependency Injection pattern, 1 2004. Dostupné z: http://www.martinfowler.com/articles/
injection.html.
[12] FRANCH, X. Systematic formulation of non-functional characteristics of software. In Requirements Engineering, 1998. Proceedings. 1998 Third International
Conference on, s. 174–181, 1998.
[13] HÅKANSSON, J. et al. The SaveCCM Language Reference Manual. Technical
report, Dept. of Computer Science and Electronics, Mälardalen University, Sweden,
2007.
[14] HANSSON, H. et al. SaveCCM - A Component Model for Safety-Critical RealTime Systems. In EUROMICRO ’04: Proceedings of the 30th EUROMICRO Conference, s. 627–635, Washington, DC, USA, 2004. IEEE Computer Society. doi:
http://dx.doi.org/10.1109/EUROMICRO.2004.72. ISBN 0-7695-2199-1.
[15] HELLESOY, A. – TIRSEN, J. PicoContainer homepage, 2008. Dostupné z: http:
//www.picocontainer.org/.
[16] JEŽEK, K. – BRADA, P. – ROHLÍK, O. Towards a Unified and Portable Descriptor
of Extra-functional Properties for Reusable Software Components. Unpublished
draft paper, Department of Computer Science and Engineering, University of West
Bohemia, Pilsen, Czech Republic, 2008. Submitted to 6th International Workshop
on Formal Engineering approaches to Software Components and Architectures,
Satellite event of ETAPS, to be held on 28th March 2009, York, UK.
[17] LIŠKA, V. Transformation from SaveCCM to CoSi. CDT412 - Software Engineering Project Report, School of Innovation, Design and Engineering, Mälardalen
University, Västeras, Sweden, December 2008.
[18] MEYER, B. Applying ’design by contract’. Computer. 1992, 25, 10, s. 40–51.
[19] SZYPERSKI, C. Component Software - Beyond Object-Oriented Programming,
1998.
[20] The OSGi Alliance. OSGi Service Platform Core Specification, Release 4.1. Technical report, 2007.
83
Literatura
[21] The OSGi Alliance. OSGi Service Platform Compendium Specification, Release
4.1. Technical report, 2007.
[22] WAJTR, B. Implementace jednoduchého komponentového modelu. Master’s thesis,
Západočeská univerzita v Plzni, Fakulta aplikovaných věd, 2007.
84
Přílohy
Specifikace komponenty - popis
nezměněných hlaviček
V této příloze jsou popsány hlavičky manifestu komponenty, které nebyly změněny v této
verzi CoSi a jsou tak shodné s [6, 22]. Gramatika použitá pro definici hodnot hlaviček
je dostupná v příloze A v [22].
Control-Class
Povinná hlavička. Specifikuje aktivátor komponenty - jméno třídy, která implementuje
rozhraní BundleControl.
Příklad:
Control - Class : cz . zcu . fav . kiv . b d c o n t a i n e r .
e x t r a f u n c r e g i s t r y s e r v i c e . impl . A c t i v a t o r
Bundle-Name
Povinná hlavička. Reprezentuje jméno komponenty.
Příklad:
Bundle - Name : E x t r a f u n c R e g i s t r y B u n d l e
Bundle-Version
Reprezentuje verzi komponenty.
Příklad:
Bundle - V e r s i o n : 1 . 2 . 3 . snapshot -10
i
Cosi-Version
Verze CoSi specifikace, pro kterou byla komponenta navržena.
Cosi - V e r s i o n ::= n u m b e r
Pro tuto verzi specifikace musí být toto číslo větší nebo rovno 2.
Bundle-Description
Krátký popis použití a účelu komponenty.
Bundle-Provider
Jméno poskytovatele komponenty.
Bundle-Classpath
Definuje seznam jar souborů uvnitř archivu komponenty, kde budou hledány přeložené
třídy, zdrojové soubory nebo jiné zdroje potřebné pro běh komponenty. Položky seznamu
jsou odděleny čárkou. Tečka (’.’) reprezentuje kořenový adresář jar archivu komponenty
a je implicitní hodnotou této hlavičky (kořenový adresář je vždy zahrnutý do class path).
Příklad:
Bundle - C l a s s p a t h : .; lib / log4j -1.3 alpha -8. jar
Generate-Events
Specifikuje události (zprávy) generované komponentou. Spolu s definicí jména musí být
uvedený typ zprávy. Tento typ je specifikován plným kvalifikovaným jménem v hodnotě
povinného atributu type. Typ události není automaticky exportován kontejnerem, je
tedy nutné ho uvést v hlavičce Provide-Types.
Parametry, které mohou být specifikovány pro událost:
version - Nepovinný parametr. Verze poskytovatele události. Implicitní hodnota je
0.
Consume-Events
Specifikuje událost vyžadované (importované) komponentou. Stejně jako v předchozí
hlavičce musí být v hodnotě atributu type uvedeno plně kvalifikované jméno typu (třídy)
ii
události. Pokud komponenta daný typ neobsahuje (tzn. ve většině případů), musí tento
typ události importovat hlavičce manifestu Require-Types.
Parametry, které mohou být pro vyžadovanou událost uvedeny:
versionrange - Nepovinný parametr. Specifikuje rozmezí verzí importované události. Implicitní hodnota parametru je [0.0.0,∞).
Provide-Attributes
Specifikuje atributy poskytované komponentou. Povinné parametry jsou jméno atributu
name a jeho typ type. Typ atributu je uveden plně kvalifikovaným jménem třídy a
musí být importován nebo exportován komponentou, aby mohla být komponenta správně
zpracována kontejnerem.
Parametry, které mohou být specifikovány pro poskytovaný atribut:
version - Nepovinný parametr. Verze poskytovaného atributu. Implicitní hodnota
je 0.
Require-Attributes
Specifikuje atributy vyžadované komponentou. Povinné parametry jsou jméno atributu
name a jeho typ type. Typ atributu je uveden plně kvalifikovaným jménem třídy a
musí být importován komponentou (uveden v hlavičce Require-Types), aby mohla
být komponenta správně zpracována kontejnerem.
Parametry, které mohou být specifikovány pro vyžadovaný atribut:
versionrange - Nepovinný parametr. Specifikuje možné rozmezí verzí importovaného atributu. Implicitní hodnota je [0.0.0,∞).
iii