Universiteit Gent Faculteit Toegepaste Wetenschappen
Vakgroep Informatietechnologie Voorzitter: Prof. Dr. Ir. Lagasse
TINA gebaseerd Subscription Management door Kristof DECLOEDT DEEL Ι
Promotor: Prof. Dr. Ir. P. DEMEESTER Thesisbegeleider: Ir. F. VANDERMEULEN
Afstudeerwerk ingediend tot het behalen van de academische graad van burgerlijk ingenieur computerwetenschappen Academiejaar 1997-1998
TINA gebaseerd Subscription Management door Kristof DECLOEDT DEEL Ι
Afstudeerwerk ingediend tot het behalen van de academische graad van burgerlijk ingenieur computerwetenschappen Academiejaar 1997-1998 Promotor: Prof. Dr. Ir. P. DEMEESTER Thesisbegeleider: Ir. F. VANDERMEULEN Faculteit Toegepaste Wetenschappen Universiteit Gent Vakgroep Informatietechnologie Voorzitter: Prof. Dr. Ir. Lagasse
II
Samenvatting Het Telecommunications Information Networking Architecture Consortium is een internationale samenwerking die een open architectuur voor telecommunicatiesystemen in het breedband, multimedia, en informatiedomein definieert en valideert. Omdat er vooral theorie bestond over dit TINA systeem, maar slechts weinig concrete uitwerkingen waren, werd in dit afstudeerwerk een dergelijke uitwerking van het Subscription Management voor dit telecommunicatiesysteem bedacht, en geïmplementeerd. In het inleidende hoofdstuk wordt de algemene TINA architectuur kort toegelicht, en wordt het Subscription Management gesitueerd. In hoofdstuk 2 wordt beslist welke functionaliteit deze laatste aan de gebruiker moet kunnen aanbieden. Dit leidt tot de gebruikers interface beschreven in het volgende hoofdstuk. Een eerder computationeel model van de provider die de functionaliteit moet implementeren, wordt gepresenteerd in hoofdstuk 4. Hier kan dan ook een vergelijking gebeuren van de ontworpen architectuur met de reeds beschreven TINA architectuur. In hoofdstuk 5 wordt nader ingegaan op de gebruikte databank: zowel de motivatie waarom een bestaande databank werd gebruikt, de soorten connectiemogelijkheden ermee, alsook de inhoudelijke structuur ervan worden besproken. Tenslotte wordt in hoofdstuk 6 een summiere studie gepresenteerd omtrent de meest geschikte programmeeromgeving voor dit afstudeerwerk. De appendices bevatten een neerslag van het verloop van de thesis, future work, tips voor mensen die aan dit of gelijkaardig onderwerp willen (verder-)werken, en tenslotte een inhoud van de bijhorende CD-ROM. Nodige voorkennis voor deze thesis zijn: - kennis van Java - kennis van CORBA, met OrbixWeb als implementatie hiervan - kennis van SQL - voldoende kennis van een OS als Windows NT (om de databank beschikbaar te stellen, en om de vele parameters manueel, wat de voorkeur geniet, te kunnen instellen) De voorliggende tekst is nu reeds lijvig genoeg, zonder deze op te blazen met extra informatie over een van deze onderwerpen. Voor verdere informatie wordt dan ook verwezen naar de literatuur die hier ruimschoots aandacht aan besteedt.
III
Dankwoord : Hierbij wil ik Prof. Demeester bedanken om het promotorschap op zich te willen nemen. Verder bedank ik Filip Vandermeulen die mijn thesisbegeleider was, een werk waar veel tijd in steekt. Ook Lieve Babylon die de audio-bestanden insprak en Kristien De Meulder die me een netwerkkaart bezorgde dewelke me toeliet om thuis te werken aan deze thesis verdienen hier zeker een vermelding. Tenslotte mag ik ook mijn ouders niet vergeten die me de financiële vrijheid lieten om deze thesis af te werken naar eigen goeddunken.
Toelating tot bruikleen "De auteur geeft de toelating dit afstudeerwerk voor consultatie beschikbaar te stellen en delen van het afstudeerwerk te copiëren voor persoonlijk gebruik. Elk ander gebruik valt onder de beperkingen van het auteursrecht, in het bijzonder met betrekking tot de verplichting de bron uitdrukkelijk te vermelden bij het aanhalen van resultaten uit dit afstudeerwerk." 1998-05-09
IV
Inhoudstafel: Hoofdstuk 1: Inleiding ……………………………………………………………………… 1 1.1 1.2
Overzicht Functie van de computationele objecten
Hoofdstuk 2: Algemene mogelijkheden van het programma ………………….……..…..… 5 2.1 2.2 2.3
Beschrijving Informatiemodel Conclusie
Hoofdstuk 3: Bespreking van de client ………………………………..…………………… 10 3.1 3.1.1 3.1.2 3.1.3 3.2 3.2.1 3.2.2 3.2.3 3.2.4 3.2.4 3.3 3.3.1 3.3.2 3.3.3 3.3.4 3.3.5 3.4 3.4.1 3.5 3.6 3.6.1 3.6.2
De login procedure Doel Gebruik Bespreking implementatie Het Service Menu Andere Aanmelding Mijn Services Gratis Services Alle Provider Services Afsluiten Het Privilege Menu Nieuwe Groep Wijzig leden Groep Wijzig Services Groep Nieuw Persoon Privilege Wis Persoon Privilege Het Rekening Menu Toon Rekening Het Optie Menu Het Help Menu Help About
V
Hoofdstuk 4: Bespreking van de servers en de serverobjecten……………………….……. 35 4.1 4.1.1 4.1.2 4.1.3 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9 4.10 4.11 4.12 4.13
Inleiding Voorgestelde Computationeel Model Wijzigingen ten opzichte van TINA Mogelijke netwerk configuratie De manager De Welcome server De User Agent Factory De User Agent De User Context Factory De User Context De Subscription Agent Factory De Subscription Agent De Subscriber Manager De Subscription Registrar De Service Template Handler Scenario's
Hoofdstuk 5: Bespreking van de Databank …………………………….…………………… 63 5.1 Motivatie gebruik databank 5.2 Connectie Mogelijkheden 5.3 Structuur van de Databank 5.3.1 Persoon 5.3.2 Terminal 5.3.3 Terminalhouders 5.3.4 Groepen 5.3.5 Groepleden 5.3.6 Rekening 5.3.7 Rekeninghouders 5.3.8 Service 5.3.9 Gratisservice 5.3.10 Grantpersoon 5.3.11 Grantgroep 5.3.12 Help
Hoofdstuk 6: Studie over JAVA-Programmeeromgevingen en Database access ….…….…. 73
VI
Appendix A: Historiek ……………………………..…....……………….…….……..…….. 75 Appendix B: Uitbreidingen en Verbeteringen …………...……………….…….….…..…… 78 1. Inleiding 2. De Client 3. De Provider 4. Denkpistes voor aanpassing Groepleden tabel Appendix C: Tijdsbesparende Tips ……..….…………………………………….……..….. 87 Appendix D: Inhoud CD-ROM ……….…..……………………………………….……….. 90
Tabel van afkortingen: TINA UA UAF UCxt SubAg STH SubM SubRg DB
:Telecommunications Information Networking Architecture :User Agent :User Agent Factory :User Context :Subscription Agent :Service Template Handler :Subscriber Manager :Subscription Registrar :Databank
VII
Hoofdstuk 1: Inleiding 1.1 Overzicht Een TINA systeem is een open gedistribueerde software omgeving, die tot doel heeft om gebruikers services aan te bieden geleverd door een of meerdere providers ervan. Deze providers kunnen op hun beurt ook zelf gebruik maken van services aangeboden door andere providers. Dit kan bijvoorbeeld nodig zijn als onderdeel van een nieuwe service die ze aanbieden, of gewoon om deze rechtsreeks te kunnen leveren aan een gebruiker die bij hem inlogt en om deze specifieke service vraagt. Of anders gezegd, de services die een gebruiker kan opvragen zijn verdeeld over een netwerk van providers die ze aanbieden. Nu zijn de TINA specificaties er onder andere op gericht om een informatie en computationeel model op te stellen van een dergelijk systeem met meerdere providers en gebruikers. De onderstaande figuur toont hoe een dergelijk systeem met meerdere providers en gebruikers er zou kunnen uitzien:
1
De volgende figuur toont de interne structuur van een provider volgens de TINA specificaties.
De verschillende computationele objecten, aangegeven door een rechthoek, kunnen zich bevinden op verschillende servers. Om gebruik te kunnen maken van een service moet een gebruiker zich inloggen op het systeem. Het gedeelte van de software dat hiervoor instaat bij de provider, noemt men het Access Session Control Subsystem. Het gedeelte dat instaat om de gebruiker te registreren bij de provider, en dat toelaat hem in te schrijven op bepaalde services, noemt men het Subscription Management Subsystem. In deze thesis zijn het deze twee subsystemen die ontwikkeld en geïmplementeerd werden, tezamen met de clientcode die ervan gebruik maakt. Verder staat het Session Control Subsystem ervoor in om effectief services aan te bieden aan de gebruiker. Het aanbieden van services moet hier in de ruimste zin van het woord verstaan worden, en omvat bijvoorbeeld ook het creëren van sessies. Deze laten toe dat meerdere gebruikers gelijktijdig deelnemen aan eenzelfde -gedistribueerde- applicatie. Een voorbeeld hiervan is een Whiteboard service die toelaat dat meerdere gebruikers gelijktijdig aan eenzelfde tekening werken. Een uitwerking van dit laatste kan gevonden worden in een parallelle thesis door Yoeri Vandevelde en Sophie Demaarschalk. Deze implementeert het TINA Session Control Subsystem door middel van 1 server, namelijk de Service Factory (SF) die tot doel heeft een dergelijke Whiteboard sessie op te zetten. Verder bevat deze thesis, naar dewelke in het vervolg zal gerefereerd worden als de "Session Control Thesis", natuurlijk ook de bijhorende client code. Alhoewel het nu reeds mogelijk is om vanuit deze thesis een service op te starten, werd de link tussen beide thesissen nog niet uitgewerkt volgens de TINA specificaties. 2
1.2 Functie van de computationele objecten: Access Session Control UA: Dit is de User Agent. Met elke gebruiker die inlogt op het systeem, wordt een UA geassocieerd, wiens referentie aan deze gebruiker wordt geretourneerd. Indien de UA nog niet bestond, wordt hij gecreëerd door de User Agent Factory (UAF) die op zijn beurt een lijst bijhoudt van alle UA's die hij aangemaakt heeft. Naast een link met het Session Control Subsystem, is dit de enige verbinding van de gebruiker met de provider. De UA zal dan ook voornamelijk als taak hebben om requests van de gebruiker, van andere UA's en vanuit het Session Control Subsystem te verwerken, door deze meestal grotendeels verder terug uit te besteden aan de andere serverobjecten waarmee hij in verbinding staat.
UCxt: Elke User Context is verbonden met juist 1 UA, wordt gemaakt door een User Context Factory en staat grofweg in voor de informatie verbonden aan de terminals waarop de gebruiker, die geassocieerd is aan de UA, werkt. Zo kan dus via de UCxt nagegaan worden op welke terminals de client aan het werken is. Dit is onder andere interessant wanneer men iemand wil uitnodigen in een sessie. Ook moet de UCxt terminal mobility ondersteunen. Onder terminal wordt hier een machine verstaan die inlogt op een provider, en zich dus ten opzichte van deze laatste als een terminal gedraagt. Dit belet dus niet dat de betreffende machine naast dit terminal gedrag ook nog andere functies heeft.
Subscription Management SubAg: Dit is een Subscription Agent object, dat in een 1:1 relatie staat met een UA. Het wordt aangemaakt door een Subscription Agent Factory, en staat in voor de verwerking van alle informatie die te maken heeft met subscription. Telkens wanneer de UA bijvoorbeeld een request binnenkrijgt die voor verwerking gegevens betreffende subscription nodig heeft, zal hij hiervoor beroep doen op de interface die hem aangeboden wordt door de SubAg.
STH: De Service Template Handler staat in voor de verwerking van alle informatie die generisch is voor alle services die de provider kan aanbieden. Elke SubAg krijgt een referentie naar dit object.
3
SubM: De Subscriber Manager houdt alle informatie bij van de gebruikers, en hun subscription portfolios. Deze laatste bevatten de informatie over contracten die gesloten worden tussen de gebruiker en de provider betreffende het gebruik van de services die hij aanbiedt. Er wordt benadrukt dat dit object onafhankelijk is van de specifieke services. De SubRg krijgt een referentie naar dit object.
SubRg: De Subscription Registrar staat in 1:1 relatie met elke service. Het bevat alle informatie specifiek aan deze service van alle personen die op deze specifieke service zijn ingeschreven. Met deze specifieke informatie worden de parameters van een service bedoeld die niet generisch zijn voor alle services.
Eenmaal in hoofdstuk 2 beslist werd aan welke specificaties het Access Session Control en het Subscription Management Subsystem in de afstudeerwerk zullen moeten voldoen, zal er in hoofdstuk 3 een architectuur vooropgesteld worden die deze functionaliteit kan implementeren. Zowel de architectuur, de werking als een vergelijking met de TINA architectuur zullen er besproken worden.
4
Hoofdstuk 2: Algemene mogelijkheden van het programma
2.1 Beschrijving Langs de providerzijde moet het mogelijk zijn om de verschillende servers waaruit de provider is opgebouwd te lanceren en te monitoren op hun werking. Hiervoor wordt de Manager server gebruikt, die na een manuele lancering, de andere servers opstart, initialiseert, en monitored. Voor een verder beschrijving van deze en andere provider servers, wordt verwezen naar hoofdstuk 4. Eenmaal de provider volledig is opgestart, kan de client gebruik maken van de aangeboden diensten. Welke diensten zijn er nu gewenst door de client? Vooreerst zijn er een aantal basisvereisten. Hij moet zich kunnen in- en uitloggen op het systeem, zich kunnen inschrijven op een service en wanneer hij is ingeschreven op een service, moet hij deze ook kunnen starten. Tijdens het inloggen op het systeem moet er nagetrokken worden of de gebruiker de betreffende computer van waaruit hij inlogt wel mag gebruiken. In eerste instantie zal de provider hiervoor moeten beschikken over een lijst die aangeeft van welke computers deze ingeschreven gebruiker allemaal eigenaar is. Deze basismogelijkheden werden alle voorzien. Daarenboven werden ook nog een aantal uitbreidingen voorzien die voor de hand liggen. Aangezien de provider zal aanrekenen voor het gebruik van een service, moet de gebruiker het saldo van zijn account kunnen nagaan. Daar een gebruiker een service kan opstarten, bijvoorbeeld louter uit privé overwegingen, of bijvoorbeeld voor zijn werk, zou het nuttig zijn mocht hij de mogelijkheid hebben om over meerdere rekeningen te beschikken bij de provider, zodat hij kan bepalen op welke rekening de service die hij start moet aangerekend worden. Het omgekeerde zou ook nuttig zijn, namelijk het toelaten dat meerdere personen services kunnen laten aanrekenen op dezelfde rekening. Zo zouden bijvoorbeeld alle bestuursleden van een bedrijf de mogelijkheid kunnen hebben om de services die zij opstarten, en gebruiken in functie van dit bedrijf, te laten aanrekenen op eenzelfde "bestuursleden" rekening. Verder zou het handig zijn dat de configuratie van de machine waarop de gebruiker werkt, nagetrokken wordt vooraleer er een poging wordt ondernomen
5
om de service effectief op te starten. Het is bijvoorbeeld overbodig om audio data door te sturen om af te spelen als de gebruiker niet beschikt over een audiokaart in zijn toestel. Dit zou enerzijds het risico op een onstabiel systeem verminderen, en anderzijds moet de kost niet worden betaald om de data, of toch ten minste een deel ervan, door te sturen naar de gebruiker. Tenslotte moet de gebruiker ook een service aan iemand anders kunnen aanbieden. Dit houdt in dat hij de toelating geeft om op een van zijn rekeningen een welbepaalde persoon, op een welbepaalde computer, een welbepaalde service te laten starten. Een voorwaarde hiervoor is natuurlijk dat diegene die de service aanbiedt, de eigenaar is van de computer waarop hij de betreffende persoon de service laat starten. Dit zal voor gevolg hebben dat een persoon niet alleen kan inloggen op de computers waarvan hij eigenaar is, maar ook op diegene waarop hij door iemand een service wordt aangeboden.
Naast deze basismogelijkheden en voor de hand liggende uitbreidingen, zijn er nog een aantal mogelijkheden die niet noodzakelijk zijn, maar die louter tot doel hebben om het gebruikersgemak te verhogen. Zo zou het handig zijn als men een aantal personen willekeurig kan groeperen, om hen dan als groep in zijn geheel ineens een service toe te kennen. Dit maakt het overbodig dat elke persoon die deel uitmaakt van deze groep, afzonderlijk deze service zou moeten aangeboden worden. Een directe uitbreiding hierop zou zijn om een groep van personen opnieuw te laten bestaan uit weer een andere groep. Dit laatste zou dus kunnen leiden tot een geneste structuur van groepen, dit tot op willekeurige diepte. Ook al deze mogelijkheden werden geïmplementeerd, zij het dat er een beperking werd ingevoerd met betrekking tot de diepte wegens een doorgevoerde performantie optimalisatie. Daar er ook code nodig is voor de gebruiker, kan er speciale aandacht besteed worden aan de GUI. Aangezien alle LayoutManagers uit de huidige Java standaard serieuze beperkingen opleggen aan de precieze plaatsing van de componenten op het scherm, en onverwacht creatief kunnen zijn wanneer een scherm 'geresized ' wordt, of zeker als de schermresolutie veranderd wordt, zou hier een eigen LayoutManager kunnen gemaakt worden. Er zijn 2 methodes die, weliswaar nog in 'hardgecodeerde vorm' en dus nog niet als effectieve LayoutManager, geïmplementeerd werden. Tenslotte beschikken meer en meer computers over multimedia capaciteiten, zodat moderne applicaties hiervan gebruik maken, onder andere voor het genereren van help informatie. Ideaal zou zijn als deze help bestanden niet vastgecodeerd zijn in de clientcode, maar dynamisch gedownloaded kunnen worden. Dit heeft als voordelen dat de inhoud van de help bestanden kan gewijzigd worden zonder dat dit ook het geval hoeft te zijn voor de clientcode, 6
en dat de client over minder opslagcapaciteit moet beschikken. Verder zou hiervoor de terminalconfiguratie moeten nagegaan worden of deze in staat is om audio of video bestanden af te spelen, om zo te kunnen beslissen in welke multimedia vorm deze help informatie zal aangeboden worden. Ondanks het feit dat de recentste Java standaard niet beschikt over enige noemenswaardige multimediacapaciteiten, en zelfs helemaal geen als het applicaties betreft, werd deze uitbreiding in de client applicatie toch verwezenlijkt.
2.2 Informatiemodel Bovengenoemde vereisten van het programma leiden tot een informatiemodel dat als volgt kan weergegeven worden:
7
2.3 Conclusie Hier zal een samenvattende lijst weergegeven worden van de bovengenoemde vereisten.
* servers lanceren en initialiseren * servers monitoren * inloggen op het systeem * zich inschrijven op een service * een service opstarten waarop de gebruiker is ingeschreven * uitloggen van het systeem * meerder rekeningen per gebruiker * meerdere eigenaars per rekening * rekeningstand opvraagbaar * configuratie natrekken vooraleer een service op te starten * services toekennen aan andere personen * services toekennen aan groepen van personen ineens * groepen van personen laten bestaan uit weer andere groepen * nieuwe LayoutManagers en gebruikers-applicatie resolutie onafhankelijk maken * audiovisuele helpinformatie * helpinformatie dynamisch downloaden van een willekeurige locatie bepaald door de provider
Hier werden dus eerst de mogelijkheden opgesomd waarover de gebruiker moet kunnen beschikken. Met deze vereisten kon een informatiemodel opgebouwd worden in 2.2. Daar de client software hier werd ontwikkeld om al deze vereisten aan te bieden aan de gebruiker, en omdat de provider software al deze vereisten implementeert, maar geen bijkomende informatie bezit, kunnen beide stukken software beschreven worden door dit zelfde informatiemodel. Anderzijds is het, mede door deze manier van werken, zo dat de functies die de client applicatie aanbiedt aan de gebruiker bijna steeds direct zullen kunnen gemapt worden op de
8
functies die de provider aanbiedt. Hierdoor ligt een computationeel model van de client voor de hand, zodat er dus kan verwezen worden naar de code hierover die zich bevindt in DEEL 2. Rest ons dus enkel nog uitleg te geven over het gebruik van de client applicatie, beschreven in hoofdstuk 3, en het computationeel model van de provider te beschrijven, wat behandeld wordt in hoofdstuk 4. Dit laat toe om deze tekst enigszins compacter voor te stellen.
9
Hoofdstuk 3: Bespreking van de client 3.1 De login procedure 3.1.1 Doel: De login procedure heeft tot doel na te gaan of de persoon die inlogt, toelating heeft om een service te gebruiken op die terminal. Deze toelating heeft hij indien iemand hem om het even welke service aanbiedt op de desbetreffende terminal, of indien hij geregistreerd staat bij de provider als (een) eigenaar van de terminal.
3.1.2 Gebruik:
De gebruiker tikt zijn loginnaam en zijn paswoord in, in de login tekstbox, respectievelijk de paswoord tekstbox. De loginnaam wordt uniek verondersteld, met als gedachte dat deze uiteindelijk zou kunnen vervangen worden door een PIN-code. Onzichtbaar voor de gebruiker wordt als derde parameter een unieke terminal identification parameter ingevuld. Deze wordt voorlopig meegegeven via de commandline. De bedoeling is echter om in de toekomst hiervoor een uniek machine-serienummer te gebruiken, of indien de terminal ook aangesloten is op het internet, eventueel het internet adres. Voorwaarde voor dit laatste is wel dat dit adres waterdicht kan getest worden. Indien de gebruiker, op welke wijze ook, deze terminal identification parameter zou kunnen wijzigen, dan zou hij alle services kunnen gebruiken op een willekeurige terminal, ook als hij de desbetreffende terminal niet mag gebruiken.
10
3.1.3 Bespreking implementatie: De paswoord dialoog is geïmplementeerd in "thesis\client\PasswordDialog.java", en is een extensie van de Dialog-klasse. Als er op de OK-button gedrukt wordt, wordt er geen dispose() aangeroepen, maar enkel een setVisible(false). Zo kunnen de waarden uit de tekstvelden nog uitgelezen worden via de functies 'login()' en 'password()'. Als layoutmanager wordt de GridBagLayoutManager gebruikt. Dit heeft wel als nadeel dat er weinig controle is over de lay-out bij resizing. De kern van de client bevindt zich in "thesis\client\StandardClient.java". Via de commandline worden als parameters de terminal identificatie en de host van de Welcome server meegegeven. Daar beide parameters persistent zijn voor elke willekeurige login vanop deze terminal, worden ze bewaard als STATIC's. Dit laat toe op eenvoudige wijze zich opnieuw aan te melden. Beide parameters worden meegegeven aan de constructor van de inner klasse Contact. Deze bindt met de Welcome server, en ontvangt via de ring-functie informatie over de permissies van de gebruiker op de terminal, op basis van het terminalnummer, de login en het paswoord. Indien de login procedure negatief is, wordt voor de gevallen de login niet bestaat, of dat het paswoord verkeerd is, dezelfde boodschap gegenereerd. Zoals reeds vermeld, is dit om privacy redenen. Indien de login en het paswoord wel correct zijn, maar de gebruiker geen enkele service mag gebruiken op de terminal wordt dit wèl gemeld in een andere boodschap. Indien de login procedure positief is, krijgt het contact-object, via deze ring-functie ook de referentie van de UA horend bij de gebruiker, en verlaat men de oneindige lus in Contact die telkens een nieuwe paswoord dialoog start als de login procedure negatief is. (Er dient opgemerkt dat dit geen busy-waiting lus is). Vervolgens kan de code in de StandardClient
nu verder uitgevoerd worden: een StandardClientFrame-object wordt
gemaakt. Dit object roept een menu op met alle aangeboden functionaliteit, en reageert op alle events gegenereerd door dit menu, door de passende klassen op te roepen. Enkel voor de optie 'automatische font', wordt geen klasse opgeroepen, maar wordt de code ter plaatse geïmplementeerd. Er werd gekozen om alle code van het menu in een aparte klasse te stoppen omdat dit anders de StandardClient te log zou maken.
11
3.2 Het Service Menu
3.2.1 Andere Aanmelding: 3.2.1.1 Doel: 'Andere aanmelding' laat toe opnieuw in te loggen. Dit kan uiteraard ook gebruikt worden om zich enkel uit te loggen. 3.2.1.2 Gebruik: De gebruiker klikt op dit item, en wordt vooraleer uit te loggen nog eerst even gewaarschuwd via een WarningDialog-object uit de thesis.reuse-package. Deze laat toe zich alsnog te bedenken. 3.2.1.3 Bespreking implementatie: Eerst wordt de clientShutDown-functie aangeroepen van de UA die zo op de hoogte komt dat de client zich heeft uitgelogd. Dit zou nog kunnen uitgebreid worden door de UA de client als het ware voortdurend te 'pingen'. Dit is nodig omdat het mogelijk is dat de client niet netjes afsluit, en dat zo dus de clientShutDown-functie niet zou aangeroepen worden. Vervolgens wordt de andereAanmelding-functie van de StandardClient opgeroepen, die ervoor zorgt dat de vorige sessie, waar dus ook de oproep voor andere aanmelding vandaan kwam, netjes opgekuist wordt. Vervolgens wordt terug dezelfde procedure doorlopen als bij de eerste login.
12
3.2.2 Mijn Services:
3.2.1.1 Doel: 'Mijn beschikbare Services' toont alle services die aangeboden worden aan de gebruiker door om het even wie, op deze specifieke terminal. Services kunnen individueel aan een gebruiker aangeboden worden, of via een groep. Dit laatste wil zeggen dat de gebruiker de service mag gebruiken omdat hij deel uitmaakt van een groep, aan wie de desbetreffende service aangeboden wordt. Het is dus perfect mogelijk dat een service via meerdere kanalen aangeboden wordt. De gebruiker krijgt daarvan een overzicht, zodat hij kan beslissen op wiens rekening hij uiteindelijk de geselecteerde service wil opstarten. 3.2.1.2 Gebruik: Om te zien welke services allemaal aangeboden worden, drukt de gebruiker op de Filter-knop. Voorlopig heeft deze benaming weinig zin, maar het is de uiteindelijke bedoeling dat de gebruiker op de lijst van aangeboden services, door middel van deze knop bepaalde filteroperaties kan uitvoeren. Zo zouden via de rekening of groep checkbox enkel die services kunnen uitgefilterd worden die aangeboden worden via respectievelijk die rekening of door die groep. Via de Uitvoerbare-checkbox, zou het mogelijk zijn niet alle aangeboden services te tonen, maar er enkel deze services uit te filteren, die vanwege de terminalconfiguratie uitvoerbaar zijn. Op dit ogenblik wordt er als voorbeeld enkel rekening gehouden met de terminal configuratie voor het tonen van help informatie. Hierin wordt nagegaan of de terminal in staat is om deze informatie in video, audio, of enkel in tekst formaat te tonen. Zie 3.6.1 voor meer uitleg over de help functie. Eenmaal de aangeboden services getoond worden, kan men zien wie ze aanbiedt, door eenmaal op de service te klikken. Als de service aangeboden wordt omdat men deel uitmaakt van een bepaalde groep, wordt dit aangetoond door een label 'groep' voor de aanbiedende groepnaam. Indien de service individueel aan de 13
gebruiker aangeboden wordt, staat er voor de rekeningnaam van de aanbiedende persoon een 'rekening' label. 3.2.1.3 Implementatie: 'Mijn beschikbare Services' is geïmplementeerd als een Frame, niet als Dialog. Dit heeft geen speciale reden, tenzij om te vergelijken met de implementatie van de andere menu items, die dan meestal wel Dialog's zijn. Als men speelt met 'setVisible()' en 'setEnabled()', komen beide implementaties op hetzelfde neer. Om de lay-out te verzorgen werd geen van de beschikbare LayoutManagers gebruikt. Deze laten immers nooit niet toe om componenten precies te plaatsen waar gewenst, en de GridBagLayout Manager, die dit enigszins wel kan, mits je de vele parameters correct kunt instellen, heeft dan weer het probleem dat de componenten niet altijd voorspelbaar verschuiven en resizen bij een herschaling van het volledige frame. Daarom werd besloten om zelf in te staan voor de plaatsing van de componenten, en het effect bij herschaling. Het komt er dus op neer dat er een nieuwe LayoutManager gemaakt is, zij het nog niet oproepbaar zoals de andere: de principes worden telkens toegepast waar nodig. De reden hiervoor is dat er een paar mogelijkheden uitgetest zijn, zodat op het einde van het afstudeerwerk, op basis van de verschillende toepassingen, zou kunnen afgewogen worden welke methode het best was. Deze zou dan uiteindelijk als volwaardige LayoutManager kunnen gecodeerd worden. Het principe dat hier gebruikt werd is het volgende. Er wordt uitgegaan van de standaardwaarden voor de afmetingen van het Frame en de fontsize. Op dit Frame worden de componenten vast geplaatst, waarna ze vermenigvuldigd worden met een schalingsfactor voor de uiteindelijk gebruikte font- en framesize. Deze werkwijze combineert beide voordelen van de bestaande LayoutManagers: de componenten kunnen precies geplaatst worden, en ze herschalen mee met de afmetingen van het frame. Verder moet de fontsize slechts eenmaal als parameter ingevuld worden. Nadeel van deze methode is dat slechts een beperkte afwijking van de standaardwaarden mogelijk is, daar bij het verkleinen van de componentafmetingen, de tekst erin niet tegelijk mag meegeschaald worden. Dit zorgde ervoor dat er later voor andere componenten een betere methode zou aangewend worden. Om niet teveel communicatie te hebben met de UA, wordt alle informatie die in dit frame kan opgevraagd worden, ineens doorgezonden. Dit is enkel een time-space tradeoff, en er werd voor deze oplossing gekozen omdat enerzijds de hoeveelheid opgevraagde informatie toch relatief beperkt is, en anderzijds in de UA door de huidige implementatie ervan, toch alle informatie voor handen is als men de aangeboden services opvraagt. Zodoende zou extra 14
communicatie, door bijvoorbeeld telkens een request te doen aan de UA wanneer de gebruiker eenmaal op een service klikt om te zien wie hem deze service aanbiedt, bij de UA alleen maar voor overhead zorgen. Natuurlijk zou men bovengenoemde beslissing niet mogen nemen om de laatstgenoemde reden, omdat de interface naar de client onafhankelijk zou moeten zijn van de implementatie van de UA, maar niettemin is het toch leuk meegenomen.
3.2.3 Gratis Services:
3.2.3.1 Doel: Via 'Gratis Services' kan de gebruiker services starten die hem niet aangerekend worden. Dit zijn dus typisch reclames.
3.2.3.2 Gebruik: Eerst moet een service geselecteerd worden, daarna zal deze starten door op start te drukken.
3.2.3.3 Implementatie: 'Gratis Services' is geïmplementeerd als een Dialog, met de lay-out gebaseerd op standaardwaarden. Door op de start-knop te drukken wordt een Service-object gecreëerd, dat geïmplementeerd is als een Thread, zodat de rest van de client hierdoor niet stilgelegd wordt. Zodoende is het overbodig dat een gebruiker meerdere malen op dezelfde terminal kan inloggen onder dezelfde naam. Als rekeningnummer wordt een lege string meegegeven met dit Service-object, zo weet de provider dat het hem om een gratis service gaat. Dit moet hij enerzijds weten omdat deze service dan niet moet worden aangerekend, maar anderzijds ook omdat de gratis services intern een andere nummering hebben dan de gewone services. Zo weet de provider op welke nummering het gekregen servicenummer slaat.
15
3.2.4 Alle Provider Services:
3.2.4.1 Doel: Via de 'Provider Services' kan eender welke service opgestart worden die de provider aanbiedt. Dit is nuttig voor de gebruiker indien hij een service wil opstarten op een van zijn eigen rekeningen. Hij kan dat altijd, maar zal ertoe genoodzaakt worden indien hij een service wil starten die hem door niemand aangeboden wordt. Voorwaarde is natuurlijk dat hij (mede-) eigenaar is van de terminal, want hoe dan ook moet hij de toelating hebben om de terminal te gebruiken. Door dubbel op een rekening te klikken wordt hierover informatie getoond, zoals het banknummer , de naam van de rekening, en de huidige stand ervan.
3.2.4.2 Gebruik: Alle services die door de provider kunnen aangeboden worden, verschijnen automatisch in de linker lijst, de rekeningen waarover de gebruiker beschikt in de rechter lijst. Uit deze lijsten selecteert de gebruiker een combinatie van de service die hij wenst op te starten, en de rekening waarop deze service mag aangerekend worden. Daarna drukt hij op de start-knop.
3.2.4.3 Implementatie: 'Provider Services' is geïmplementeerd als een Dialog, met een lay-out gebaseerd op standaardwaarden.
3.2.4 Afsluiten: Laat toe om af te sluiten zonder daarna direct opnieuw aan te melden. Er wordt hier terug een Warning-dialog getoond, die toelaat dat de gebruiker zich alsnog bedenkt.
16
3.3 Het Privilege Menu
3.3.1 Nieuwe Groep:
3.3.1.1 Doel: Met 'Nieuwe Groep' is het mogelijk om een nieuwe groep te maken. Deze zal aangerekend worden op een rekening, geselecteerd uit de rekeningen waarvan diegene die de groep aanmaakt (mede-)eigenaar van is. Verder kan elke persoon alleen die groepen zien, gebruiken, het ledenbestand ervan aanpassen, of volledig wissen, waarvan hij (mede-)eigenaar is van de rekening waarop de betreffende groep aangerekend wordt.
3.3.1.2 Gebruik: De nieuwe naam van de groep kan zelf ingetikt worden. Door op de rekeningen knop te drukken, verschijnen alle rekeningen waarover de gebruiker beschikt. Hieruit kan hij dan een selecteren waarop de groep mag aangerekend worden. Er dient opgemerkt dat deze rekening niet manueel kan ingevuld worden: dit zou anders enkel kunnen leiden tot fouten. De rekeningen zullen verschijnen onder hun cryptische naam, maar het exacte banknummer kan opgevraagd worden door er dubbel op te klikken. De uitleg tekstbox dient om wat uitleg
17
te geven over de nieuwe groep. Iedereen die over de groep beschikt, of er deel van uitmaakt, kan deze uitleg zien, en gebruiken als geheugensteuntje over de inhoud of betekenis van de groep. Door op de voeg toe knop te drukken wordt de groep definitief gemaakt. Door op de gedaan knop te drukken, verlaat men 'Nieuwe Groep' zonder de groep te maken, tenzij men al op de voeg toe knop gedrukt heeft.
3.3.1.3 Implementatie: 'Nieuwe Groep' is een Dialog met een lay-out gebaseerd op standaardwaarden.
3.3.2 Wijzig leden Groep:
3.3.2.1 Doel: Hiermee kan men aan een bestaande groep een aantal personen of groepen toevoegen, of verwijderen, op voorwaarde dat de eerstgenoemde groep aangerekend wordt op een rekening waarvan men eigenaar is. Diezelfde voorwaarde geldt voor de groepen die men wil toevoegen daar het enkel deze groepen zullen zijn die zichtbaar zijn voor de persoon die het ledenbestand wijzigt. Het is ook mogelijk om de volledige groep te wissen. Als de groep gewist wordt, dan verdwijnt deze ook uit alle groepen die deze gewiste groep bevatten. Het is mogelijk om groepen tot op een willekeurige diepte te nesten.
3.3.2.2 Gebruik: Om de groep die aangepast moet worden te selecteren, moet op de corresponderende selecteertoets gedrukt worden. Hierdoor verschijnen in de rechter lijst alle groepen die de gebruiker kan bewerken, met andere woorden, alle groepen die aangerekend worden op een
18
rekening die hij bezit. Door een van deze groepen te selecteren, verschijnt de groepsnaam, de rekening waarop de groep aangerekend wordt en de leden van de groep in de corresponderende linker tekstboxen. Door op de Wis Groep knop te drukken wordt de groep volledig verwijderd, alsook in alle groepen waarin hij geïncludeerd is. De gebruiker kan een groep van personen includeren in de groep door op de Groepen knop te drukken. Hierdoor verschijnen alle groepen in de rechter lijst die terug voldoen aan bovenstaande voorwaarde. Door hieruit een groep te selecteren, en op de Voeg Toe knop te drukken, zal de groep toegevoegd worden. Om een persoon toe te voegen bestaan er 2 mogelijkheden: ofwel drukt men op de Extra Lid knop, en kan men manueel een login van een persoon invullen (die zal gecontroleerd worden op zijn bestaan), ofwel selecteert men eerst een groep, en drukt men daarna op de Toon Leden knop. Hierdoor zullen alle leden verschijnen behorend tot de aangeklikte groep. Wanneer op een selecteerknop gedrukt wordt, en er zo in de rechter lijst bepaalde gegevens getoond worden, verandert het label van de knop automatisch in '<<' wat aangeeft dat door op deze knop te drukken, het geselecteerde item uit de rechter lijst, zal overgebracht worden in de corresponderende linker tekstbox. De Wis Alles knop die ervoor zou zorgen dat alle leden van een groep ineens zouden verwijderd worden, zonder dat de groep zelf wordt verwijderd, is nog niet geïmplementeerd. Door dubbel te klikken op het rekening tekstveld verschijnt alle informatie over de betreffende rekening: het banknummer, de rekeningnaam, en de stand van deze rekening bij de provider. Bij dubbelklikken op een groep verschijnt de uitleg die de maker van de groep eraan heeft meegegeven, en bij dubbelklikken op een persoon, wordt zijn naam, adres en geboortedatum weergegeven. Eventueel zou het voor een gebruiker mogelijk zijn, om niet toe te laten dat sommige van deze gegevens getoond worden.
3.3.2.3 Implementatie: De code bevindt zich in "thesis\client\GroepLedenDialog.java", en is geïmplementeerd als Frame. Hier wordt echter de tweede methode van lay-out toegepast. Omdat in de vorige werkwijze de fontsize roet in het eten gooide, werd hier speciale aandacht besteed om dit probleem op te lossen. Daar letters geen andere componenten kunnen bevatten, maar zelf wel in andere componenten kunnen voorkomen, en aldus een invloed hebben op de gewenste grootte van deze laatste, wordt de fontsize gebruikt als basiseenheid van (relatieve) afmeting van de componenten. Hetzelfde geldt voor de plaatsing van een component in een andere component. Een direct gevolg en voordeel hiervan is dat men onmiddellijk de minimumafmetingen krijgt van de componenten, wat later de waarde van getPreferredSize() 19
zou kunnen worden. Om de componenten ook te kunnen herschalen, wordt er naast deze basiseenheid, ook nog een secundaire eenheid gebruikt: een eenheid die de speling van de componenten voorstelt, en bekomen wordt als het verschil tussen de minimum en de gevraagde size. Deze speling kan in verschillende eenheden voorgesteld worden, en dan volledig verdeeld worden over de verschillende componenten. In een echte LayoutManager zou deze speling kunnen uitgedrukt worden in procenten. Hier werd de speling gedeeld in een willekeurig aantal delen. Deze werkwijze houdt zo niet alleen rekening met de afmetingen van de verschillende componenten, maar ook met de grootte van de tekst die erin komt, en presteert beter dan de vorige. Er moet wel gezegd dat op zijn beurt, er hier enkel rekening wordt gehouden met de fontsize, en dus niet met de horizontale afmetingen van de tekst. Voor deze laatste wordt als ruwe schatting de fontsize per karakter gebruikt, wat in sommige gevallen, een te kleine of te grote schatting kan zijn. De afwijkingen zullen echter nooit zeer groot zijn. Wanneer op basis van deze methode een LayoutManager zou gebouwd worden, zou hier liefst wel exact rekening mee gehouden moeten worden. De naamgeving van de rechter lijst in de code, is meestal gebaseerd op de eerste letters van inhoud die er kan in verschijnen, of die het in een eerdere versie deed. Er wordt nagegaan of alle tekstvelden ingevuld zijn als er op de Voeg Toe knop gedrukt wordt. Als de gebruiker een volledige groep wil wissen, wordt er nog eerst een waarschuwing gegeven om zich alsnog te bedenken. Dit is zeker niet overbodig, omdat als nevenwerking de desbetreffende groep ook verdwijnt uit alle groepen waar hij deel van uitmaakt. Zoals bij alle andere menu items, wordt ook hier een Frame op het scherm gezet met de melding om even geduld te hebben tijdens de uitvoering van een opdracht. Dit is nuttig omdat er anders een tijdje niets gebeurt, en de gebruiker eventueel nogmaals op de zelfde knop zou drukken. Indien het de Voeg Toe knop betreft, zou dit als gevolg hebben dat als reactie op de tweede aanvraag, er op het scherm verschijnt dat de groep of persoon niet kan toegevoegd worden omdat deze reeds opgenomen is in de te bewerken groep. Alhoewel het dan toch duidelijk zou moeten zijn wat uitgevoerd is, en wat niet omdat in de linker lijst telkens de laatste inhoud van het ledenbestand getoond wordt, is dit toch niet wenselijk: noch voor de gebruiker, noch voor de performantie. Bij resizing wordt ook hier nagegaan of men de minimum afmetingen, bepaald door de tekst, en zijn fontsize, niet overschreden wordt. Zo ja, wordt voor de richting(en) die overschreden wordt, de minimum afmeting gebruikt.
20
3.3.3 Wijzig Services Groep:
3.3.3.1 Doel: Met 'Wijzig Services Groep' kunnen de services die aangeboden worden aan de leden van deze groep op een bepaalde terminal gewijzigd worden. 3.3.3.2 Gebruik: Op dezelfde wijze als hierboven beschreven moet de groep worden geselecteerd waarvan de aangeboden services moeten gewijzigd worden. Hierdoor verschijnt ook automatisch de rekening waarop de groep aangerekend wordt. Vervolgens kan een terminal geselecteerd worden waarover de gebruiker beschikt. Na beide bewerkingen, verschijnen alle services die reeds zijn aangeboden aan de geselecteerde groep en op de geselecteerde terminal in de Service lijst. Door op de Wis Groep knop te drukken kan men, na positief te antwoorden op de gegenereerde waarschuwing, de volledige groep wissen, met inbegrip van de reeds vermelde nevenwerkingen. Door een service te selecteren en op de Wis Item knop te drukken wordt de geselecteerde service verwijderd. Door op de service knop te drukken verschijnen in de rechter lijst alle services die de provider aanbiedt. Hieruit kan men een willekeurige service selecteren. Door op de Voeg Toe knop te drukken, zal deze service nu op de geselecteerde terminal aangeboden worden aan de groep. Bij dubbelklikken op een item uit een lijst, verschijnt dezelfde informatie als bij het creëren van een nieuwe groep. Als extra mogelijkheid kan men hier ook op een terminal klikken, waardoor de terminal identificatie en de naam die aan de terminal gegeven werd, weergegeven worden. Een verbetering zou erin bestaan om een extra knop aan te bieden die alle terminals toont waarop de groep minstens een service aangeboden wordt, op voorwaarde dat de gebruiker telkens eigenaar ervan is.
21
3.3.3.3 Implementatie: Het
item
'Wijzig
Services
Groep'
wordt
geïmplementeerd
in
"thesis\client\GroepServiceDialog.java". Het is een Frame die laatste lay-out methode gebruikt.
22
3.3.4 Nieuw Persoon Privilege:
3.3.4.1 Doel: Met 'Nieuw Persoon Privilege' kan een bepaalde persoon een bepaalde service aangeboden worden op een specifieke terminal, op een bepaalde rekening. Deze combinatie wordt verder een privilege genoemd. Een persoon kan dit ook aangeboden worden via opname in een groep. Met de voorlopige uitwerking van de UI verdient dit zelfs de aanbeveling, omdat dit voor diegene die de service aanbiedt eenvoudiger te manipuleren is.
3.3.4.2 Gebruik: Er zijn 2 mogelijkheden om een persoon te selecteren aan wie men een privilege wil toekennen. Ofwel kan men de login van de persoon manueel invullen, ofwel kan men de persoon halen uit de lijst die alle personen bevat aan wie men reeds individueel een privilege heeft toegekend. Hiervoor moet eerst op de Selecteer knop worden gedrukt. Op dezelfde wijze vult men de Privilege, Terminal en Rekening tekstbox in. Door op de Voeg Toe knop te drukken, kent men het privilege effectief toe. Door op de Gedaan knop te drukken, verlaat men 'Nieuw Persoon Privilege' zonder hiermee het privilege toe te kennen, tenzij men reeds op de Voeg Toe knop gedrukt heeft. Een verbetering zou erin bestaan de selecties voor de tekstboxen niet onafhankelijk van elkaar te laten verlopen, maar ook toe te laten dat de items die in de rechter lijst getoond worden, reeds gefilterd zijn op basis van de reeds ingevulde tekstboxen. Verder zal door dubbel te klikken op een item in de rechter lijst, er over dit item informatie verschijnen.
23
3.3.4.3 Implementatie: Het
item
'Nieuw
Persoon
Privilege'
werd
geïmplementeerd
in
"thesis\client\NieuwePersoonPrivilegeDialog.java". Het is een Dialog met een lay-out gebaseerd op de eerste methode.
3.3.5 Wis Persoon Privilege:
Dit menu item kan kort beschreven worden als volgt: Het is volledig analoog aan het menu item 'Nieuw Persoon Privilege', behalve dat het een privilege verwijdert, in plaats van toevoegt. Voor de rest is het doel, het gebruik met de opmerkingen hierbij, en de implementatie volledig gelijklopend.
24
3.4 Het Rekening Menu
3.4.1 Toon Rekening:
3.4.1.1 Doel: Dit menu item laat toe alle informatie te bekijken van de rekeningen waar de gebruiker eigenaar van is: Er kan opgevraagd worden wie allemaal er nog mede eigenaar is van de rekening, welke personen of groepen er gebruik maken van de rekening, wat de naam en het banknummer ervan is, en tenslotte wat de huidige stand van de rekening is bij de provider. Deze functionaliteit zou verder nog kunnen uitgebreid worden met extra informatie betreffende de stand van de rekening. Daar echter het 'billing-systeem' nog niet is uitgewerkt, kan hier nog geen verdere account informatie gegeven worden.
3.4.1.2 Gebruik: De linker lijst wordt automatisch ingevuld met de namen van de rekeningen waarover de gebruiker beschikt. Door op de Gebruikers knop te drukken verschijnen in de rechter lijst alle personen die de rekening gebruiken omdat ze individueel een service aangeboden zijn op de geselecteerde rekening. Verder verschijnen ook alle groepen die aangerekend worden op de rekening. Door dubbel te klikken op een groep, verschijnt de uitleg erover die de maker ervan 25
aan deze groep heeft meegegeven. Het onderscheid tussen personen en groepen wordt aangegeven door een corresponderende prefix. Door op de Mede-eigenaars knop te drukken verschijnt in de rechter lijst de login van alle personen die ook eigenaar zijn van de betreffende rekening. Door dubbel te klikken op een van deze login's, zal de volledige naam van de persoon weergegeven worden, alsook zijn adres en geboortedatum.
3.4.1.3 Implementatie: Het
'Toon
Rekeningen"
menu
item
werd
geïmplementeerd
in
"thesis\client\RekeningDialog.java" en is een Frame dat gebruik maakt van de tweede lay-out methode.
26
3.5 Het Optie Menu
Deze checkbox heeft tot doel het automatisch instellen van de fontsize. Deze wordt berekend op de grootte van het menuframe, en zal verder gebruikt worden in alle menu items. Warningframes blijven echter in de standaard 12 punt font. Java laat wel de keuze van een font toe, ook voor het menu, maar laat voor de MenuBar niet toe dat de hoogte aangepast wordt. Dit is mijns inziens een tekortkoming in de huidige JAVA standaard, en leidt ertoe dat de font niet lineair kan meegeschaald worden met de grootte van het frame, omdat anders in de MenuBar niet de volledige letters kunnen getoond worden bij een grote font. Daarom werd er een parabolische functie toegepast op de frame size, die de automatische fontsize oplevert. Dit is eigenlijk niet ideaal, maar kan niet anders met de huidige JAVA versie. Daar enerzijds het programma zo toch ook functioneert, en daar anderzijds enkel deze parabolische functie moet omgezet worden naar een lineaire functie, eenmaal er een JAVA versie komt die wèl toelaat dat de hoogte van de MenuBar eventueel automatisch aangepast wordt, kan de optie van automatische font nu al aangeboden worden. Daar initieel de grootte van het menu-frame relatief bepaald wordt ten opzichte van het volledige scherm, zal dit ertoe leiden dat alle vensters en fonts er op elk scherm relatief gezien hetzelfde zullen uitzien, en dus resolutieonafhankelijk zijn, wat uiteindelijk in de lijn ligt van de principes van JAVA. (Wegens de gedwongen parabolische in plaats van lineaire functie zal voorlopig de UI er ongeveer, maar niet altijd exact hetzelfde uitzien op schermen met verschillende resolutie.) Dat men hier de font willekeurig mag aanpassen, iets wat men in de meeste programma's meestal niet kan, ligt hem onder andere in het feit dat niets wat op het scherm komt moet uitgeprint worden. Door het veranderen van de fontsize, zodat de letters bij verschillende schermresoluties op het scherm even groot blijven, zouden deze op papier wel veranderen van grootte, indien er geen speciale conversie gebeurt. Indien men echter toch een groter of kleiner lettertype wenst, kan dit door op het overeenkomstige menu item te drukken. Hierdoor wordt de automatische font uitgeschakeld. 27
Naast de resolutie onafhankelijkheid kan er nog een ander, zij het minder belangrijk voordeel aangehaald worden. Door dezelfde resolutie onafhankelijkheid kan men op deze manier altijd werken op de hoogst haalbare resolutie, wat de kwaliteit van de letters ten goede komt. Verder kan door resizen, bij keuze van automatische font, deze font automatisch verkleind worden, zodat de volledige vensterinhoud zichtbaar blijft. Dit laatste kan voor sommige gebruikers de voorkeur genieten boven het behouden van de font grootte, maar het resoluut afknippen van een deel van de inhoud van het venster. Daar de MenuBar niet resizable is, is er een beperking opgelegd aan het interval van mogelijke font groottes.
28
3.6 Het Help Menu
3.6.1 Help: Indien de gebruiker dit menu item aanklikt, wordt nagegaan via de terminalconfiguratie, of deze terminal audio en/of video kan afspelen. Afhankelijk van deze configuratie krijgt de gebruiker een korte video te zien, een tekst te horen en een helptekst te zien. Het is zo dat gelijk waar in het programma hulp kan worden ingeroepen, door dubbel op een label te klikken. Voor de meeste gevallen geldt dit ook als er dubbel geklikt wordt op een item uit een lijst of tekstbox. Wat de vorm is van de hulp die aangeboden wordt, is afhankelijk van de configuratie van de terminal. Om enerzijds ruimte bij de client te sparen, en anderzijds automatisch de laatste versie van help bestanden te kunnen geven, worden de helpbestanden niet bij de client geplaatst, maar kunnen zich om op het even welke URL bevinden. Het geheel van de aangeboden hulp kan als voorbeeld dienen van gebruikersvriendelijkheid, als voorbeeld van het gebruik van de UCxt, en eigenlijk ook als een begin van een Distributed Processing Environment, of multi provider systeem. Ondanks dat JAVA de naam heeft uitstekend te zijn op gebied van multimedia, heb ik ondervonden dat dit op dit ogenblik met een grove korrel zout moet genomen worden. De huidige versie 1.1 en zelfs de toekomstige versie 1.2 van JAVA laat op multimedia gebied qua 'video' enkel sprite animations toe, en dus geen echte videoformaten zoals .mpg, .avi, .mov enz. Op gebied van audio moet men het stellen met audiofiles die enkel van het .au type mogen zijn en die beperkt zijn tot 8 kHz. Bovendien is dit alles slechts toepasbaar in applets, en niet in applications! Van 'multimedia' weinig sprake dus… Ik heb echter na een zoektocht op het net, een bèta versie op de kop kunnen tikken van de JMF ( Java Media Framework). Deze bèta versie leidt niet aan bovenstaande beperkingen, en zal in een van de komende JAVA versies, zij het nog niet de eerstvolgende, beschikbaar zijn. Daar enkel de .CLASS files beschikbaar werden gesteld, en niet de source code ervan, liet 29
JBuider niet toe om een project te compileren die deze klassen importeerde. Daarom werd het bestand "thesis\reuse\MediaPlayer.java" vanuit de commandline gecompileerd, en werd er in het project een stub bestand gebruikt. Om het geheel te laten werken, moeten eerst het project met de stubfile vanuit JBuilder gecompileerd worden, alsook de java bestanden uit "\MediaPlayer" en zijn subdirectories. De gegenereerde CLASS bestanden van dit laatste dienen dan gecopieerd te worden over de stub CLASS-bestanden. De audio helpbestanden worden afgespeeld als mono, 16bit, 22kHz WAV bestanden: deze bieden voor het gehoor optimale kwaliteit, terwijl hun omvang toch slechts ¼ bedraagt van bestanden opgeslagen met CD-kwaliteit. Indien het volledige afstudeerwerk op 1 PC wordt gedraaid, dus met inbegrip van alle provider servers, zal er hoogstwaarschijnlijk niet meer genoeg CPU-time over zijn om de videobestanden af te spelen op volle snelheid. (halve of 1/10 snelheid lukt wel) Of een type kan afgespeeld worden, hangt mede af van het onderliggende besturingssysteem. Er moet wel rekening mee gehouden worden dat dit toch nog altijd maar een bèta versie is. Zo gebeurt het wel eens dat audio omslaat in ruis, maar door het afspelen te stoppen door het venstertje met de vooruitgangsbalk te sluiten, en de help opnieuw op te starten door dubbel te klikken op hetzelfde item, zal dit mankement zich normaal geen 2 maal na elkaar voordoen. Ongetwijfeld brengt de definitieve JMF-versie verbeteringen aan omtrent deze problemen. De gebruikte versie van JMF staat 'ter evaluatie' op de CD-ROM onder "\JMF".
Implementatie: Om help informatie te kunnen tonen, bevat iedere klasse die een menu item voorstelt, een inner class waar er telkens een instantie van wordt gecreëerd die een listener is van een object waar help moet voor beschikbaar zijn. Dit object wordt geïnitialiseerd met een string die uniek het object waarvoor help opgevraagd moet worden, identificeert. Om de juiste vorm (i.e. tekst, audio, video,…) van helpinformatie te kunnen krijgen van de UA, moet dit helpobject ook kunnen beschikken over het terminalnummer, en voor latere implementatie van personal profiles, ook over de persoonsidentificatie. Om deze laatste 2 parameters samen met de UA referentie niet telkens te moeten meegeven, worden ze als STATIC geïmplementeerd, in de Help klasse. Deze helpklasse bevindt zich in "thesis\reuse\Help.java" en de STATIC variabelen worden hun waarde geassigneerd door het StandardClientFrame. Alle informatie die nodig is om help te kunnen geven, wordt opgevraagd na het aanklikken van een menuitem. Deze informatie bestaat enkel uit de URL's van de audio en video bestanden, en de helptekst. Ondanks dat dit geen grote hoeveelheid data is, wordt er toch een 30
cache van deze gegevens aangelegd, zodat die gegevens uit de cache kunnen gehaald worden als hetzelfde menu item nogmaals wordt aangeklikt. Voorlopig worden de 3 boolean variabelen in elk helpobject die voorstellen of er respectievelijk de video, audio of tekstuele vorm van help gewenst is, op true gezet. Dit zou als uitbreiding door de gebruiker kunnen bepaald worden, en zou dan ook deel van de profiles kunnen uitmaken. Doordat deze variabelen dus op true staan, worden enkel bepaalde vormen van help (audio-video-tekst) uitgeschakeld, als deze ofwel niet beschikbaar zijn, of als de terminal configuratie een bepaalde vorm niet toelaat. Als om een van deze redenen een helpbestand niet kan getoond worden, wordt door de UA een lege string als URL teruggegeven. Indien er bijvoorbeeld wel een audio help bestand kan afgespeeld worden, dan wordt de verkregen URL meegegeven aan de MediaPlayer die zich in "\MediaPlayer\thesis\reuse\MediaPlayer.java" bevindt. Om een MediaPlayer te kunnen afspelen, moet er in de constructor een MediaListener worden meegegeven, die aangeroepen wordt als het Mediabestand afgespeeld is. Deze MediaListener interface bevindt zich in "thesis\reuse\MediaListener.java". Daar de helpklasse deze interface implementeert, en dan een referentie meegeeft van zichzelf aan de MediaPlayer, wordt hij op de hoogte gebracht wanneer het Mediabestand ten einde is. Dit is het moment waarop het helpobject de help-tekstbox op het scherm zal zetten. Eigenlijk zou ook de help functie zelf moeten beschouwd worden als een service. Voorlopig is dit niet het geval. Voorbeeld van audio help informatie als dubbel geklikt wordt op een label:
31
Waarom de help functie in wezen eigenlijk ook een service is, wordt geïllustreerd in volgende figuur.
Wanneer dubbel op die welbepaalde service wordt geklikt, verschijnt video help informatie. In dit geval zou net dezelfde video clip kunnen getoond worden als reclame service, dus als er op start wordt gedrukt. Dit geval maakt duidelijk dat de help functie eigenlijk ook een service is, en dat deze dan in de toekomst ook computationeel op dezelfde wijze zou moeten uitgewerkt worden.
3.6.2 About: Deze Aboutbox wordt geïmplementeerd in "thesis\reuse\AboutBox"
32
3.7 Services 3.7.1 Algemeen Zoals reeds vermeld, werd het TINA systeem opgesplitst in deze thesis en in de "Session Control Thesis". Daar beiden vanaf nul moesten starten, hebben we ons hoofdzakelijk toegelegd op ons domein, en was de link tussen beiden voorzien voor volgend jaar. Er werden enkele afspraken gemaakt zodat er zo weinig mogelijk dubbel werk zou verricht worden, en dat beide systemen eenvoudig op elkaar zouden passen. Op het einde van ons programmeerwerk, hebben we toch beide systemen aan elkaar gelinkt. Er moet duidelijk onderlijnd worden dat dit enkel als demo dient, om te illustreren dat het geheel tezamen werkt: beide systemen hangen slechts samen met een zijden draadje dat bestaat uit een object van de Service klasse, die zich bevindt in "thesis\client\Service.java". Als een service opgestart wordt, wordt een dergelijk object gemaakt, dat als argumenten van de constructor onder andere de service naam, het service nummer, het banknummer, en een referentie naar de SF meekrijgt. Dit service object werd geïmplementeerd als een afzonderlijke Thread, zodat de rest van de client kan blijven doorwerken. Daar de code van het serviceobject van voorlopige aard is, en enkel dient als demo, tot de verdeling van de taken tussen het subscription systeem en het service gedeelte nader bepaald wordt, werd geen aandacht besteed om deze code generisch te maken. Met andere woorden, beide systemen werden afzonderlijk uitgewerkt, maar de 'cement' tussen beide onderdelen, kan onderwerp zijn van een volgende thesis. Voor alle duidelijkheid: bij de link tussen beide systemen moet helemaal niet gezocht worden naar TINA principes! Als extra voorbeeldje van een service, om mee te experimenteren, werd een eenvoudige grafische toepassing gemaakt, die beschreven wordt in volgend punt. De andere grafische toepassing, die onderwerp is van de "Session Control Thesis", kan ook opgeroepen worden als service, en de code bevindt zich in "ShWhite".
33
3.7.2 Grafische transformaties:
Als voorbeeld van een beschikbare service werd een heel eenvoudig demo programma geschreven. Het bevindt zich in "thesis\service\transformaties". In tegenstelling tot de WhiteBoard-service is het in staat om volledig parallel uitgevoerd te worden met de oproepende applicatie. Het is mogelijk om in een linker tekenblad resolutie onafhankelijk lijnstukken te tekenen (de relatieve resolutie bij schaal (1.0,1.0) werd bepaald op (1000,1000)). Tegelijk wordt in het rechter tekenblad een getransformeerde versie getekend, via een op te geven 2x2 matrix. De code is zo geschreven dat een willekeurig aantal van die rechter tekenbladen kunnen worden aangemaakt die synchroon met het linker blad de figuur meetekenen. De achterliggende reden is dat deze bladen zich even goed zouden kunnen bevinden bij een andere gebruiker. Er kan ook een grid op het tekenblad gelegd worden met willekeurige relatieve afstanden tussen de punten. Bij dubbelklikken wordt de aaneenschakeling van lijnstukken gesloten, en tenslotte zal bij het indrukken van de Shift toets en het gelijktijdig indrukken van de muisknop, het dichtste hoekpunt van de figuur geselecteerd worden, en kan deze versleept worden. Indien de gridfunctie niet aanstaat gebeurt dit verslepen op continue wijze, indien de gridfunctie wel aanstaat, op discontinue wijze van het ene gridpunt naar het andere. Verder is het mogelijk dat de bladen kunnen herschaald worden (en dus een andere relatieve resolutie krijgen), of dat de bladen geresized worden, wat de figuur zal aanpassen in absolute waarden, maar niet de relatieve.
34
Hoofdstuk 4: Bespreking van de Servers en de serverobjecten 4.1 Inleiding Hier wordt de structuur en de werking van de verschillende serverobjecten besproken. Daar JAVA zichzelf nogal goed documentarieert, wordt voor detailinformatie verwezen naar de code die zich in DEEL ΙΙ : JAVA Code bevindt. Wat de IDL interfaces betreft worden hier enkel de functies ervan besproken. Voor de exacte definitie van de types wordt terug verwezen naar DEEL ΙΙ, onderdeel IDL Interfaces. Daar het informatiemodel reeds werd gegeven in hoofdstuk 2, kunnen we ons hier hoofdzakelijk beperken tot een computationeel model. Voor alle duidelijkheid zal eerst de naamgeving van de interfaces uitgelegd worden. Er worden alleen kleine letters gebruikt, alle interfacenamen hebben de suffix 'if', en de scheiding tussen de woorden onderling en de suffix waaruit de interface naam is samengesteld, wordt voorgesteld door een '_'. Indien een object A een interface implementeert, bedoeld om gebruikt te worden door object B, dan is de naam 'A_B_if'. Elk object A heeft ook telkens een interface die een extensie is van alle interfaces die dit object A aanbiedt. De naam hiervan is 'A_if'.
35
4.1.1 Voorgestelde Computationeel Model: Dit model ziet eruit als volgt:
In lichtgrijs werd de "Session Control Thesis" weergegeven. De verschillende provider componenten kunnen zich bevinden op verschillende servers. Hun functie en werking wordt hieronder beschreven.
4.1.2 Wijzigingen ten opzichte van TINA De wijzigingen werden aangegeven in een groene kleur. Zoals op zicht te zien, zijn deze nihil. In plaats van de SubM te verbinden met de SubRg, wordt deze momenteel verbonden met de SubAg. Dit heeft voorlopig weinig belang daar de SubM nog geen functionaliteit bezit. Meer informatie hierover is te vinden in 4.10. Hetgeen in rode kleur staat, zijn wijzigingen aangebracht aan de TINA specificaties waarvan werd uitgegaan, maar die blijkbaar in parallel ook in de recentste specificaties (mei 98) op dezelfde wijze zijn aangebracht, zij het onder een andere naam (Initial Agent).
36
4.1.3 Mogelijke netwerk configuratie Hieronder wordt een mogelijke netwerk configuratie weergegeven. De "Session Control Thesis" werd weergegeven in een groene kleur.
37
4.2 De manager 4.2.1 Werking en structuur De interne structuur van de manager ziet eruit als volgt:
De volle pijlen stellen een instantiëring voor, de gesloten lege pijl een referentie, en de open pijl een listener. De manager wordt manueel gestart, waarna er een UI verschijnt. Via deze UI kunnen de andere servers opgestart worden via het "Start Up" menu item. Hierdoor worden eerst alle servers opgestart, en worden alle parameters waarvoor er al waarden beschikbaar zijn, geïnitialiseerd. Dit zijn de parameters om de databank te kunnen aanspreken. Daarna worden de link parameters geconfigureerd. Dit zijn de referenties naar de andere servers. Deze initialisatie kan als volgt weergegeven worden:
Hierbij stellen de grote pijlen een bind voor door de manager server. De kleine pijlen tonen de referenties die meegegeven worden door de manager tijdens de initialisatiefase.
38
Via het view menu kunnen de aanvragen op de interfaces van de verschillende opgestarte servers gemonitored worden. Via de sub-menu's wordt er hiervoor een fijnere granulariteit aangeboden. Als een interface van server A aangeboden aan object B moet gemonitored worden, dan gaat de aanvraag om monitoring informatie te zenden naar de manager, naar de server die de aanvraag doet. Dit laat toe om zonder extra code, bij de monitoring informatie niet alleen de aangesproken functie van een interface te vermelden, maar ook wie hem opgevraagd heeft. Een uitzondering hierop is de client, omdat dit enerzijds niet goed zou zijn voor de performantie, en anderzijds omdat de client beter niet in rechtstreeks contact staat met de manager. Verder kunnen ook onverwachte excepties en databank aanvragen gemonitored worden. Het "Shut Down" menu item legt alle servers stil, behalve de SF, daar deze niet door mij geprogrammeerd werd, en nog niet de nodige interface bezit. Het "Exit" menu item doet net hetzelfde, maar verlaat ook het programma.
4.2.2 Aangeboden interfaces module manager{ interface monitor_if{ void monitor(in string in string in string in string in string }; };
bron_server, doel_server, if, time, text);
Deze wordt gebruikt door de servers die gemonitored worden, om hun monitoring informatie op te sturen. Het tekst argument dient om extra informatie mee te geven. Dit wordt bijvoorbeeld gedaan indien er een error optreedt, dan komt in 'tekst' een omschrijving van deze error. De bron_server parameter bevat de naam van de server of het serverobject van waaruit de functie aangeroepen wordt. De doel_server bevat de naam van de server of het serverobject dat de aangeroepen functie ontvangt.
39
4.3 De Welcome server 4.3.1 Werking en structuur De Welcome server staat in voor de loginprocedure. Zowel de naam, het ermee corresponderende paswoord, als de toelating om op de desbetreffende terminal te werken, wordt nagegaan. Hiervoor doet de client een bind op een 'Welcome object' tijdens de paswoord dialoog. De informatie van deze dialoog alsmede de terminal identificatie worden doorgegeven aan het welcome object. Deze retourneert dan enerzijds een antwoord op de meegegeven parameters: voor de log in naam een true als deze bestaat, voor het paswoord een true als deze correct is voor de log in naam, een true als de terminal geregistreerd is bij de provider, en tenslotte een true als de persoon de toelating heeft om op de terminal te werken. Anderzijds wordt al dan niet de referentie van de UA corresponderend met de gebruiker geretourneeerd, naar gelang de inlogprocedure geslaagd is.
4.3.2 Aangeboden interfaces module welcome{ interface welcome_manager_if{ void ref(in manager::monitor_if monitor_if_ref, in ua::uaf_welcome_if uaf_welcome_if_ref); void setDatabaseValues(in string driver, in string properties, in string user, in string password); void monitor(in string obj, in boolean onoff); void shutdown(); }; … };
Deze interface wordt aangeboden aan de manager:
* Via ref kan de Manager de referenties van zichzelf, en van de UAF doorgeven aan de Welcome server. Deze referenties worden door de manager doorgegeven met als type de specifieke interface die beide objecten aanbieden aan de Welcome server, zodat niet alle functionaliteit kan aangeroepen worden door Welcome.
40
* setDatabaseValues laat de Manager toe om de databaseparameters door te geven. De driver parameter bevat de driver die gebruikt wordt om de DB aan te spreken, wat hier "sun.jdbc.odbc.JdbcOdbcDriver" is. De protocolparameter bevat de naam van het protocol en de naam van de DB. Hier is dit bijvoorbeeld "jdbc:odbc:databank"
* Met monitor kan de Manager de Welcome server vragen het gebruik van bepaalde interfaces te melden aan hem, alsook de requests van de client, de interactie met de databank, en eventuele foutmeldingen.
* Door shutDown aan te roepen komt de Welcome server in een operational disabled state. Een uitbreiding zou erin bestaan om ook een administrative locked/unlocked state toe te laten. Deze is minder drastisch, en is een mooiere oplossing als de server slechts tijdelijk moet uitgeschakeld worden. Ook zou het met deze methode mogelijk zijn om slechts een gedeelte van de server stil te leggen. module welcome{ interface welcome_client_if{ exception NotReady{string reason;}; boolean ring(in long terminal_nr, in string user_login, in string password, out boolean terminal_exist, out boolean user_exist, out boolean password_ok, out ua::ua_client_if useragent) raises(NotReady); void killConnection() raises(NotReady); //boolean tryAdres(in person_type user) raises(NotReady); }; … interface welcome_if:welcome_client_if,welcome_manager_if; };
Deze interface wordt aangeboden aan de client.
* ring : Laat toe om op basis van de login parameter, te beslissen of de client toegang krijgt tot het systeem. Zo nee, wordt via de return variabelen de precieze reden gegeven waarom niet, zo ja, wordt een referentie van de UA weergegeven. Er dient opgemerkt dat de precieze reden waarom een client niet toegelaten wordt, niet als dusdanig aan de gebruiker wordt weergegeven. dit om redenen van privacy, zoals reeds eerder aangehaald.
41
* killConnection: Wordt aangeroepen door de client wanneer deze uitlogt. Voorlopig maakt enkel de UCxt gebruik van deze informatie: zo weet deze immers op welke terminals de gebruiker ingelogd is.
* tryAdres: Werd in een oorspronkelijk ontwerp gebruikt om na te gaan of een persoon reeds een service was aangeboden door iemand anders, vooraleer ingeschreven te zijn. Wegens redenen van privacy en security werd dit achterwege gelaten.
42
4.4 De User Agent Factory 4.4.1 Werking en structuur De UAF geeft een referentie terug van een UA telkens de Welcome server hierom vraagt. Er zijn 2 mogelijkheden om aan deze referentie te geraken: ofwel heeft de client die geassocieerd wordt aan de gevraagde UA nog nooit ingelogd, en dan zal de UAF een nieuwe UA maken, wiens referentie hij dan retourneert aan de Welcome server en ook in een hashtable stopt. Ofwel heeft de client wel al eens ingelogd, en dan zal de referentie van de UA die bij deze client hoort, opgehaald worden uit de hashtable. In het geval een nieuwe UA moet gemaakt worden, zal de UAF deze zien met de meest uitgebreide interface (ua_if). Deze interface is een extensie van alle interfaces die de UA aanbiedt. Om deze referentie door te geven aan de client via het welcome object, zal deze algemeenste interface omgezet worden naar de ”ua_client_if” interface, die enkel die functies zal laten aanroepen die voor de client zichtbaar moeten zijn. Omdat alle informatie van een gebruiker zich in de DB bevindt wanneer hij op geen enkele terminal nog is ingelogd, is het mogelijk dat de UA dan vernietigd wordt. Dit is een kleine moeite, aangezien de UCxt een lijst bijhoudt van de terminals waarop de gebruiker is ingelogd, en zou een goede keuze zijn in de toekomst. Dit zou ondermeer toelaten dat het aantal actieve objecten drastisch daalt. Ook de objecten die deze UA’s kunnen laten creëren via de UAF, is stof voor uitbreiding.(zie Appendix B) De UAF laat de SubAg Factory en de UCxt Factory een nieuw object aanmaken dat wordt meegegeven met de UA. De manager bezit enkel de referentie van de UAF, en niet van de UA’s. Dit maakt dat de databankparameters, en de waarden van de parameters die bepalen wat de UA moet monitoren, zullen worden doorgegeven via de UAF. Deze informatie is algemeen voor alle UA’s en wordt dus geïmplementeerd als STATIC’s.
4.4.2 Aangeboden interfaces module ua{ interface uaf_manager_if{ oneway void ref(in in in in //in
manager::monitor_if subag::subagf_uaf_if ucxt::ucxtf_uaf_if string sf::sf_ua_if
43
monitor_ref, subagf_ref, ucxt_ref, sf_ref); //// service_factory_ref);
oneway void setDatabaseValues(in in in in
string string string string
driver, properties, user, password);
void monitor(in string obj, in boolean onoff); void shutdown(); }; … };
Deze interface wordt aangeboden aan de manager. Wegens de analogie met de welcome_manager_if interface, zullen enkel de verschillen met deze laatste besproken worden. In ref wordt onder andere een string meegegeven die de referentie voorstelt naar
de
servicefactory. Er wordt een string meegegeven omdat deze toelaat de SF te wijzigen, zonder daarmee ook de interface te moeten veranderen. Daar de link tussen Access Session Control en Session Control nog niet kon uitgewerkt worden, werd de optie om toch een referentie mee te geven in plaats van een string open gelaten. Een consequente naamgeving zou leiden tot iets in de stijl van de uitgecommentarieerde regel. Voorwaarde is dan wel dat deze referentie van een interfacetype zou zijn die alle SF's implementeren, zoniet zou er teveel code moeten veranderd worden wanneer er een nieuwe SF bijkomt.
module ua{ interface uaf_welcome_if{ ua_client_if getUserAgent(in long persoonnummer); }; … };
Deze interface wordt aangeboden aan de Welcome server, en laat toe dat deze laatste via getUserAgent een referentie kan krijgen op basis van de persoon die inlogt. Deze persoon wordt intern voorgesteld door een unieke persoonsidentificatie. Dit is een nummer dat automatisch zal gegenereerd worden binnen de DB. Belangrijk is dat wanneer een persoon zich uitschrijft op het systeem, en zijn identificatienummer dus vrijkomt, dat dit nummer niet zal hergebruikt worden, maar dat gewoon verder geteld wordt. De UAF hoeft geen extra security tests meer te doen daar deze al gebeurd zijn in Welcome. Indien de persoon voor de eerste keer inlogt, zal een nieuwe UA worden gemaakt, indien de UA reeds bestond zal de referentie van deze laatste uit een hashtable worden gehaald. interface uaf_if:uaf_manager_if, uaf_welcome_if;
44
Deze interface is een extensie van alle interfaces die de UAF aanbiedt. Dit is nuttig voor de manager: door een bind te doen met deze interface, kan deze gecast worden naar een willekeurige interface die aangeboden wordt door de UAF. Dit is nodig wanneer de referentie van de UAF doorgegeven wordt aan andere serverobjecten.
4.5 De User Agent 4.5.1 Werking en structuur Eenmaal de login procedure achter de rug is, moet alle interactie met het providerdomein gebeuren via de UA. ( Interactie van services zelf niet meegerekend) Deze UA kan op zijn beurt gebruik maken van de SubAg en de UCxt om te kunnen voldoen aan de client requests. Op dit ogenblik is het zo dat de meeste functionaliteit die kan aangeroepen worden door de client door de UA zelf opgelost wordt, zonder hulp van de UCxt of de SubAg. Normaal gezien zal de UA echter eerder dienen om alle binnenkomende requests te verdelen onder de serverobjecten waarmee hij in verbinding staat. Daar ten eerste de UA voorlopig slechts relatief weinig functionaliteit heeft, ten tweede deze functionaliteit snel kan verdeeld worden over bijvoorbeeld de UCxt en de SubAg, zonder dat de code daar wezenlijk door moet veranderen, is dit voorlopig van minder belang, wat niet belet dat dit in de toekomst zeker nog moet aangepast worden (zie Appendix B:Uitbreidingen) Als voorbeeld van de verdeling van de functionaliteit aangeboden door de UA aan de client werden de functies providerServices, gratisProviderServices en mijnGroepen reeds verdeeld over de verschillende servers. De UA zou in de toekomst ook nog een interface moeten aanbieden aan de service controle eenheid.
45
4.5.2 Aangeboden interfaces module ua{ interface ua_client_if{ exception NotReady{string reason;};
//controle functies: void setClientRef(in long terminal_nummer, in client::client_ua_if client_ref) raises(NotReady); void clientShutDown(in long terminal_nummer)raises(NotReady); string getSessionFactoryRef(in string type, in long service_nummer) raises(NotReady);
//functies voor het opvragen van informatie types::mijn_services_useq mijnServices(in long terminalnummer) raises(NotReady); types::provider_services_useq providerServices()raises(NotReady); types::gratis_provider_services_useq gratisProviderServices() raises(NotReady); types::mijn_terminals_useq mijnTerminals()raises(NotReady); types::mijn_rekeningen_useq mijnRekeningen()raises(NotReady); types::toon_leden_useq medeRekeningEigenaars(in string rekeningnr) raises(NotReady); types::toon_structuur_groep_useq rekeningGebruikers(in string rekeningnr) raises(NotReady); types::mijn_rekeningen_struct toonRekening(in long groepnummer) raises(NotReady); types::help_struct getHelp(in long terminalnummer, in string caller)raises(NotReady); types::toon_leden_useq toonPersonen()raises(NotReady); types::mijn_groepen_useq mijnGroepen()raises(NotReady); types::toon_leden_useq toonLeden(in long groepnummer) raises(NotReady); types::toon_structuur_groep_useq toonStructuurGroep(in long groepnummer) raises(NotReady);
46
types::provider_services_useq toonGroepServices(in long groep, in long terminal) raises(NotReady);
//functies die nieuwe informatie toevoegen of verwijderen void addPersoonPrivilege(in in in in in
string long long string string
persoonlogin, privilegenummer, terminalnummer, rekeningnummer, rekeningnaam)raises(NotReady);
void wisPersoonPrivilege(in in in in
string long long string
persoonlogin, privilegenummer, terminalnummer, rekeningnummer)raises(NotReady);
void addGroepPrivilege(in long groepsnummer, in long privilegenummer, in long terminalnummer)raises(NotReady); void wisGroepPrivilege(in long groepnummer, in long privilegenummer, in long terminalnummer)raises(NotReady);
//functies die het ledenbestand van een groep aanpassen void addGroep(in string naam, in string uitleg, in string rekeningnummer)raises(NotReady);
void addGroepGroep(in long groepnummerhoofd, in long groepnummersub)raises(NotReady); void addPersoonGroep(in string persoonlogin, in long groepnummer)raises(NotReady);
void wisGroepUitGroep(in long hoofdgroep, in long subgroep)raises(NotReady); void wisPersoonUitGroep(in long hoofdgroep, in long persoon)raises(NotReady); void wisGroep(in long groep)raises(NotReady); }; … };
Deze interface wordt aangeboden aan de client.
47
Controle Functies: * setClientRef : Alhoewel de client nog geen functionaliteit aanbiedt aan de UA, geeft hij toch al zijn referentie door aan de UA zodat deze later in staat zou zijn om de interface die de client hem aanbiedt te gebruiken.
* clientShutDown: Wanneer de client uitlogt, wordt eerst deze functie aangeroepen. Het laat de UCxt toe een lijst bij te houden op welke terminals de gebruiker ingelogd is.
* getSessionFactory: Alhoewel er op dit ogenblik nog maar 1 SF beschikbaar is, laat deze functie nu al toe dat verschillende services verschillende SF's kunnen gebruiken. Voorlopig wordt hier de naam SF gebruikt, maar niets belet om dit te veranderen als er een andere structuur komt in de Session Control. Er wordt hier nogmaals op gewezen dat de link tussen deze thesis en de "Session Control Thesis" niet werd uitgewerkt. De link heeft enkel tot doel een demo te kunnen tonen, en er moet bijgevolg ook geen enkel TINA principe achter gezocht worden!
Functies om informatie op te vragen: * mijnServices: Deze functie geeft alle services weer die een bepaalde gebruiker aangeboden worden op een bepaalde terminal. Er wordt telkens ook bepaald wie hem deze services aanbiedt. Deze services betreffen zowel diegene die hem individueel aangeboden worden, alsook de services die aangeboden worden aan elke groep waar hij deel van uitmaakt. Daar de UA weet welke gebruiker hem aanroept, maar niet vanop welke terminal, moet enkel de identificatie van deze laatste, onzichtbaar voor de gebruiker, als argument meegegeven worden. Voor deze terminalidentificatie wordt voorlopig een nummer gebruikt dat als commandline parameter meegegeven wordt. Het is echter de bedoeling dat hiervoor een onvervalsbaar nummer kan gebruikt worden zoals een machine serienummer. Indien men het IP adres van een computer kan verifiëren kan ook dit nummer gebruikt worden.(zie Appendix B:Uitbreidingen) Indien dit nummer zou kunnen vervalst worden, dan zou het immers mogelijk zijn dat iedere gebruiker gebruik kan maken van een willekeurige machine! Naast de lijst van services wordt direct nog extra informatie meegegeven, bijvoorbeeld over de groepen die een bepaalde service aanbieden.
48
* providerServices: Hierdoor kan de lijst opgevraagd worden van alle services die de provider kan aanbieden. Deze functie wordt niet door de UA zelf uitgewerkt, maar wordt doorgegeven aan de SubAg. Dit is dus een van de uitgewerkte voorbeelden betreffende de verdeling van de functionaliteit die kan opgevraagd worden via de interface van de UA, over de verschillende servers die hiervoor geschikt zijn. Voor de verdere uitwerking van deze functie, wordt verwezen naar de interface van de SubAg, die in 4.9 beschreven wordt.
* gratisProviderServices: Hierdoor kan de lijst opgevraagd worden van alle services die via de provider gratis worden aangeboden. Ook deze functie wordt niet door de UA uitgewerkt, maar wordt doorgegeven aan de SubAg. Voor uitwerking van deze functie wordt aldus verwezen naar de beschrijving van de interface van de SubAg.
* mijnTerminals: Deze functie retourneert alle terminalidentificaties waarvan de gebruiker eigenaar is. Dit is het geval als hij als dusdanig geregistreerd staat bij de provider. Om security en juridische redenen gebeurt dit (nog) niet via het programma, maar via de ouderwetse, maar meest gebruikte manier van het briefpapier.
* mijnRekeningen: Laat alle rekeningen zien waarvan de gebruiker eigenaar is. Wanneer hij eigenaar is, hoe hij het wordt, en waarom is hetzelfde als het eigenaarsschap van de terminals. Naast het rekeningnummer en de naam die eraan gegeven werd, wordt ook de uitgebreidere uitleg meegegeven alsook de account ervan. Dit laatste kan voorlopig gezien worden als het tegoed van de provider, maar dit kan wijzigen bij verdere uitwerking van het billingsysteem( de Accounting Agent, de Accounting Server e.d.)
* medeRekeningEigenaars: Deze functie retourneert alle eigenaars van de als argument meegegeven rekening. De geretourneerde informatie bevat onder andere ook de adressen van deze eigenaars.
* rekeningGebruikers: Geeft een lijst met alle personen die individueel een service zijn aangeboden op een specifieke rekening, alsook alle groepen die op deze rekening aangerekend worden.
* toonRekening: Toont info over de rekening van de groep die als argument werd meegegeven. 49
* getHelp: Als argumenten heeft deze functie de terminalidentificatie en een string, die het onderwerp beschrijft waarover helpinformatie gewenst is, nodig. Eerst wordt de DB onderzocht op de verschillende vormen waaronder de helpinformatie beschikbaar is. Dit kan onder de vorm van tekst, audio of video zijn. Indien er een tekst beschikbaar is, wordt deze opgehaald. Indien er audio of video beschikbaar is, wordt de URL waarop deze te vinden is, opgehaald. Daarna wordt aan de UCxt gevraagd om na te gaan welke van deze vormen kunnen worden getoond op basis van de configuratie van de terminal. Daar de gebruiker eventueel op meerdere terminals tegelijk kan ingelogd zijn, en deze terminals een totaal verschillende configuratie kunnen hebben, wordt natuurlijk de configuratie van die terminal nagegaan waarop de gebruiker zijn aanvraag voor deze helpfunctie doet. Een AND van beide resultaten wordt nu geretourneerd aan de client.
* toonPersonen: Geeft een lijst van personen terug die op een of andere wijze een service genieten die aangerekend wordt op een of andere rekening waarvan de gebruiker eigenaar is.
* mijnGroepen: Hierdoor worden alle groepen weergegeven waarvan de gebruiker eigenaar is. Met eigenaar wordt bedoeld, diegene die eigenaar is van de rekening waarop de groep aangerekend wordt. Deze functie is de enige manier om een groep zichtbaar te maken zonder er zelf deel van uit te maken. Deze definitie is de strengste die kan toegepast worden op gebied van security en privacy. Ook deze functie werd als voorbeeld niet in de UA geïmplementeerd, maar wordt voor verdere verwerking doorgegeven aan de SubAg.
* toonLeden: Geeft alle leden weer die behoren tot de als argument meegegeven groep. De geretourneerde lijst bevat enkel de personen die lid zijn van de groep, niet de eventuele subgroepen.
* toonStructuurGroep: In tegenstelling met toonLeden, worden hier ook de subgroepen weergegeven.
* toonGroepServices: Geeft alle services weer die de als argument meegegeven groep aangeboden zijn op de eveneens als argument meegegeven terminalidentificatie.
50
Functies die informatie toevoegen of verwijderen: * addPersoonPrivilege: Kent een privilege toe aan een persoon. Omdat bij de client enkel de login van de persoon manueel kan ingevuld worden, wordt enkel het bestaan van deze persoon gecontroleerd. De waarden van de andere argumenten werden bekomen door een item te selecteren uit een lijst, die eerder aan de UA werd opgevraagd, en kunnen dus geen foute informatie bevatten. Vooraleer het privilege effectief toe te voegen aan de DB, wordt gecontroleerd of dit privilege reeds niet bestaat. Zo ja wordt dit als een exceptie gemeld aan de gebruiker.
* wisPersoonPrivilege: Neemt een privilege weg van een persoon. Vooraleer het privilege te verwijderen, wordt nagegaan of de ingevulde parameters juist zijn. Daar hier terug enkel de login van een persoon zelf kan ingevuld worden, zal dit de enige bron van foutieve parameterwaarden kunnen zijn. Indien het te verwijderen privilege niet bestond, zal dit als een exceptie gemeld worden aan de gebruiker.
* addGroepPrivilege: Kent een nieuw privilege toe aan een groep. Dat alle meegegeven argumenten moeten geselecteerd worden uit getoonde lijsten, en dus niet zelf kunnen worden ingetikt, vermijdt niet alleen dat de gebruiker foutieve gegevens invoert, maar heeft als bijkomend voordeel dat er een DB transactie wordt uitgespaard om na te gaan of de ingevoerde gegevens wel correct zijn.
* wisGroepPrivilege: Verwijdert een privilege dat werd toegekend aan een groep. Indien het privilege niet kan verwijderd worden omdat het niet bestaat, wordt dit via een exceptie aan de gebruiker gemeld.
* addGroep: Laat toe om een nieuwe groep te creëren. Hierbij mag de naam van de nieuwe groep reeds bestaan, op voorwaarde dat de nieuwe groep niet wordt aangerekend op dezelfde rekening van de andere gelijknamige groep. Indien deze combinatie van groepnaam en rekening reeds bestaat, zal de nieuwe groep niet worden gemaakt, en zal dit gemeld worden aan de gebruiker via een exceptie. //functies die het ledenbestand van een groep aanpassen
51
Het groeperen van personen in groepen is een uitbreiding van het programma. Het toelaten dat in deze groepen andere groepen worden opgenomen, is hier nog eens een uitbreiding bovenop. Deze leidt tot een acyclisch gerichte graaf met als knopen de groepen, en met als takken de relatie "… bevat groep …". Deze structuur kan er in sommige gevallen toe leiden dat de DB recursief doorlopen moet worden, tijdens het opvragen van informatie. Om de performantie te verhogen, werd daarna nog eens optimalisatie doorgevoerd die dit omzeilde. Deze optimalisatie heeft voor gevolg dat er een voorlopige beperking bestaat, die enkel aanpassingen van het ledenbestand van een groep in de hoogste 2 lagen van de graaf toelaat. Meer informatie hierover, en een beschrijving hoe ook deze laatste beperking kan opgeheven worden, vindt men in hoofdstuk 6. Ik meen dat de implementatie van deze uitbreiding, van een optimalisatie van een uitbreiding, reeds ver buiten het kader van deze thesis ligt, waardoor ze dus gerust mag gezien worden als "future work".
* addGroepGroep: Deze functie laat toe dat het ledenbestand van een bestaande groep uitgebreid wordt met (het ledenbestand van) een andere groep. Dit leidt tot een geneste structuur die kan voorgesteld worden door bovengenoemde acyclisch graaf.
* addPersoonGroep: Laat toe om een persoon toe te voegen in een groep.
* wisGroepUitGroep: Verwijdert een groep uit het ledenbestand van een andere groep. Deze eerste groep wordt een subgroep van de tweede genoemd.
* wisGroep: Verwijdert een groep volledig: deze groep wordt dus ook verwijderd uit het ledenbestand van alle andere groepen. Voor alle duidelijkheid: hier wordt enkel de logische groepering van personen gewijzigd, niet de personen zelf die er deel van uitmaken.
52
4.6 De User Context Factory 4.6.1 Werking en structuur Op vraag van de UAF zal de UCxt Factory een UCxt object maken. Dit nieuwe UCxt object zal in een 1:1 relatie staan met een UA.
4.6.2 Aangeboden interfaces module ucxt{ interface ucxtf_uaf_if{ ucxt_ua_if getUserContext(in long persoonnummer); }; };
Deze interface wordt gebruikt door de UAF
* getUserContext: Creëert een nieuwe UCxt, op basis van de persoonsidentificatie die als argument wordt meegegeven. De referentie wordt geretourneerd aan de UAF, die deze functie telkenmale zal aanroepen als er een nieuwe UA moet worden gemaakt. (zie 4.4 )
module ucxt{ interface ucxtf_manager_if{ oneway void ref(in manager::monitor_if
monitor_ref);
oneway void setDatabaseValues(in in in in
driver, properties, user, password);
string string string string
void monitor(in string obj, in boolean onoff); void shutdown(); }; … interface ucxtf_if: ucxtf_manager_if,ucxtf_uaf_if; };
Deze interfaces bieden dezelfde functionaliteit aan als de overeenkomstige interfaces van de Welcome server. Voor verdere uitleg hierover wordt dan ook terugverwezen naar 4.3 .
53
4.7 De User Context 4.7.1 Werking en structuur De UCxt houdt bij op welke terminals de gebruiker ingelogd is. Hij beschikt ook over alle informatie die specifiek betrekking heeft op een welbepaalde terminal, zoals de terminalconfiguratie. Deze kan bijvoorbeeld opgevraagd worden om na te gaan in welke vorm men best de helpfunctie aanbiedt: in tekstuele, audio of video vorm, of een combinatie ervan.
4.7.2 Aangeboden interfaces module ucxt{ interface ucxt_ua_if{ exception NotReady{string reason;}; void add(in long terminalNummerArg, in client::client_ua_if client_ref)raises(NotReady); void wis(in long terminalNummerArg)raises(NotReady); void getConfig(in long terminalNummer, out long audio_khz, out long video)raises(NotReady); }; … };
Deze interface wordt gebruikt door de UA. * add: Voegt een terminal toe aan de lijst van terminals waarop de gebruiker is ingelogd. Deze functie wordt telkens aangeroepen wanneer een gebruiker inlogt. Er zal een exceptie gegenereerd worden wanneer de gebruiker meer dan 1 keer op dezelfde terminal probeert in te loggen. Dit laatste is immers overbodig omdat op een terminal meerdere services tegelijk kunnen opgestart worden.
* wis: Verwijdert een terminal uit de lijst van terminals waarop een gebruiker is ingelogd. Deze functie wordt opgeroepen telkens een gebruiker uitlogt. Als uitbreiding zou de UCxt zelf op geregelde tijdstippen moeten controleren of de gebruiker waarmee hij geassocieerd is, nog steeds ingelogd is. Zo kan nagegaan worden of de client niet gecrashed is zonder dat er een log out geweest is. Ook zou er nog een analoge functie moeten aangeboden worden die suspending toelaat van een sessie in plaats van definitief uit te loggen. Dit laatste zou gemakkelijker terminal mobility toelaten (zie Appendix B)
54
* getConfig: Gaat na over welke configuratie de terminal beschikt, waarvan de identificatie als argument wordt meegegeven. Deze configuratie bevat op de ogenblik enkel informatie over de mogelijkheid om audio en video af te spelen. Indien een '0' wordt geretourneerd, is de terminal niet in staat om de corresponderende vormen van multimedia af te spelen. Het exacte getal dat wordt weergegeven kan bijvoorbeeld bij video voorstellen welke formaten er kunnen afgespeeld worden. Die mogelijkheid is aanwezig, maar er wordt nog geen gebruik van gemaakt. Wanneer dit laatste uitgewerkt wordt, zou het wel beter zijn om een 'struct' te gebruiken in plaats van losse getallen. Dit zorgt er immers voor dat er bij verdere wijzigingen minder code moet aangepast worden.
55
4.8 De Subscription Agent Factory 4.8.1 Werking en structuur De Subscription Agent Factory (SubAg Factory) wordt gelanceerd door de manager, en krijgt van deze laatste de referenties van de SubM, de STH en de SubRg server mee. Telkens wanneer de UAF erom vraagt, wordt er een nieuw SubAg object gemaakt, wiens referentie dan wordt geretourneerd. Dit nieuw SubAg object krijgt de referenties naar de SubM, STH en SubRg server mee. Naar de manager wordt dezelfde interface geboden als bij de UAF.
4.8.2 Aangeboden interfaces module subag{ interface subagf_uaf_if{ subag_ua_if getSubscriptionAgent(in long persoonnummer); }; … }; Deze interface wordt aangeboden aan de UAF
* getSubscriptionAgent: Maakt een nieuw SubAg object, en retourneert er de referentie van. module subag{ interface subagf_manager_if{ oneway void ref(in in in in
manager::monitor_if subm::subm_subag_if subrg::subrg_subag_if sth::sth_subag_if
oneway void setDatabaseValues(in in in in
string string string string
monitor_ref, subm_ref, subrg_ref, sth_ref);
driver, properties, user, password);
void monitor(in string obj, in boolean onoff); void shutdown(); }; … interface subagf_if: subagf_manager_if,subagf_uaf_if; };
Deze interfaces bieden terug dezelfde functionaliteit aan als de overeenkomstige interfaces van de Welcome server. Voor verdere uitleg hierover wordt terugverwezen naar 4.3 .
56
4.9 De Subscription Agent 4.9.1 Werking en structuur Er wordt een SubAg gekoppeld aan elke UA. Deze SubAg staat momenteel in voor de uitwerking van een aantal functies die de UA aanbiedt aan de gebruiker. ( 4.9.2 toont welke functies). Sommige worden in de SubAg zelf uitgewerkt, voor anderen wordt de STH ingeroepen. Uiteindelijk is het de bedoeling dat deze SubAg instaat voor de verwerking van alle informatie die betrekking heeft op subscription, waarbij gebruik kan gemaakt worden van de interface aangeboden door de SubM, de STH en de SubRg waarmee deze SubAg verbonden is.
4.9.2 Aangeboden interfaces module subag{ interface subag_ua_if{ exception NotReady{string reason;}; types::mijn_groepen_useq mijnGroepen()raises(NotReady); types::provider_services_useq providerServices()raises(NotReady); types::gratis_provider_services_useq gratisProviderServices() raises(NotReady); }; … };
Deze interface wordt aangeboden aan de UA. * mijnGroepen: Deze functie wordt volledig in de SubAg zelf verwerkt, en geeft een lijst terug die alle groepen bevat waar de gebruiker eigenaar van is. Hierbij wordt er ook nog extra informatie meegegeven die uitleg verschaft over de groep zelf.
* providerServices: Deze functie, die een lijst retourneert van alle services die aangeboden worden door de provider, werd geïmplementeerd in de STH. De SubAg die gebruik van deze STH zal hier enkel dienen als tussenpersoon om de functieaanvraag en de geretourneerde waarde doorspelen.
* gratisProviderServices: zelfde opmerking als bij providerServices.
57
4.10 De Subscriber Manager 4.10.1 Werking en structuur Deze server bevat enkel initialisatie functionaliteit. Dit komt omdat enerzijds een groot deel van de functies die in deze server thuishoren op dit ogenblik kunnen worden uitgevoerd door de UI van de gebruikte databank (hier MS Access). Anderzijds werd het overige deel van de functionaliteit direct in de UA zelf geïmplementeerd. De code van dit laatste deel zou dus in de toekomst enkel moeten verplaatst worden naar de SubM server. (zie Appendix B)
4.10.2 Aangeboden interfaces module subm{ interface subm_subag_if{ }; … };
Deze interface moet nog ingevuld worden, en dient ter gebruik van de SubAg. module subm{ interface subm_manager_if oneway void ref(in manager::monitor_if oneway void setDatabaseValues(in in in in
string string string string
monitor_ref); driver, properties, user, password);
void monitor(in string obj, in boolean onoff); void shutdown(); }; … interface subm_if: subm_manager_if,subm_subag_if; };
Deze interfaces bieden dezelfde functionaliteit aan als de overeenkomstige interfaces van de Welcome server. Voor verdere uitleg wordt dan ook naar 4.3 verwezen.
Verder zou er ook nog een speciale interface kunnen gemaakt worden naar de manager toe zodat deze door middel van die interface, en een nog te ontwikkelen UI, de functionaliteit kan aanbieden die nu nog gebruikt wordt van de front end van MS Access.
58
4.11 De Subscription Registrar 4.11.1 Werking en structuur Ook deze server bevat naast initialisatie code geen functionaliteit: Enerzijds zijn service profiles eerder "optioneel" wanneer een totaal nieuw subscription management systeem moet gebouwd worden, en anderzijds waren er nog geen services beschikbaar, zodat er ook geen service-specifieke inschrijvingsinformatie kon gevraagd worden van de subscriber.
4.11.2 Aangeboden interfaces module subrg{ interface subrg_subag_if{ }; … };
Deze interface moet nog ingevuld worden, en dient ter gebruik van de SubAg. module subrg{ interface subrg_manager_if{ oneway void ref(in manager::monitor_if oneway void setDatabaseValues(in in in in
string string string string
monitor_ref); driver, properties, user, password);
void monitor(in string obj, in boolean onoff); void shutdown(); }; … interface subrg_if: subrg_manager_if,subrg_subag_if; };
Deze interfaces bieden dezelfde functionaliteit aan als de overeenkomstige interfaces van Welcome. Voor verdere uitleg wordt dan ook naar 4.3 verwezen.
59
4.12 De Service Template Handler 4.12.1 Werking en structuur In de uitwerking staat deze server in voor het geven van de lijsten met alle gratis services of met alle provider services. Verder moet deze server nog functionaliteit bevatten die generisch is voor alle services. De uitwerking hiervan volgt wellicht wanneer er een aantal services beschikbaar zijn. De referentie van deze server wordt meegegeven aan de SubAg.
4.12.2 Aangeboden interfaces module sth{ interface sth_subag_if{ exception NotReady{string reason;}; types::provider_services_useq providerServices()raises(NotReady); types::gratis_provider_services_useq gratisProviderServices() raises(NotReady); }; … };
Deze interface wordt gebruikt door de SubAg. * providerServices: Geeft en lijst terug van alle services die de provider aanbiedt. * gratisProviderServices: Geeft een lijst terug van alle services die gratis worden aangeboden. Dit zijn normaal gezien reclames. module sth{ interface sth_manager_if{ oneway void ref(in manager::monitor_if oneway void setDatabaseValues(in in in in
string string string string
monitor_ref); driver, properties, user, password);
void monitor(in string obj, in boolean onoff); void shutdown(); }; … interface sth_if: sth_manager_if,sth_subag_if; };
Deze interfaces bieden dezelfde functionaliteit aan als de overeenkomstige interfaces van Welcome. Voor verdere uitleg wordt dan ook naar 4.3 verwezen.
60
4.13 Scenario's Scenario voor een client die voor de eerste keer inlogt:
Scenario voor een client die inlogt, maar niet voor de eerste keer. Dit scenario is hetzelfde als de gebruiker meerdere sessies opent op extra computers.
Scenario als de gebruiker dubbel op een label klikt en dus help informatie wil:
61
Scenario als de lijst opgevraagd wordt van alle services die de provider kan aanbieden:
Scenario als alle groepen opgevraagd worden die de gebruiker mag zien, m.a.w. alle groepen waarvan de gebruiker eigenaar is:
62
Hoofdstuk 5: Bespreking van de Databank 5.1 Motivatie gebruik databank Er werd vrij snel besloten om een databank te gebruiken. Voordelen hiervan zijn: * Laat toe om sneller te programmeren door de aldus ontstane vorm van software reuse. * De mogelijkheden zijn veel uitgebreider dan zelf zou kunnen worden aangeboden. * Een goede UI. * Zal nooit meer bugs bevatten dan een snel ontwikkelde eigen 'databank'. * Biedt een gestandaardiseerde interface (SQL), die het direct ook mogelijk maakt dat de gebruikte DB uit het systeem gelicht, en er een andere in de plaats ingeplugd wordt.
Nadelen: * Alhoewel het de tijd bespaart om zelf een databank te programmeren, moet er toch ook tijd worden uitgetrokken om de methodes te leren kennen om de databank aan te spreken. (zie 6.2) en om de geschikte DB te selecteren, met de geschikte protocol keuze. Daar de keuze betreffende de DB vrij beperkt was, werd hieraan geen aandacht besteed.
63
5.2 Connectie Mogelijkheden De verschillende mogelijkheden om vanuit JAVA een connectie te leggen met een DB, of protocollen, worden in onderstaande figuur weergegeven, en daarna kort besproken.
Er bestaan 4 mogelijkheden om vanuit JAVA een DB aan te spreken. Gemeenschappelijk aan deze methodes is dat de JAVA programmeeromgeving moet beschikken over een SQLpackage. Deze is noodzakelijk wil men een connectie, op welke wijze ook, leggen met een DB.
Werking: 1) JDBC-ODBC bridge (Blauw): De DB laat via het onderliggende besturingssysteem toe, dat er een 'ODBC' connectie met hem wordt gelegd. Hiervoor is er een ODBC driver nodig, specifiek voor de DB. Deze driver wordt meestal geleverd door de DB fabrikant, maar kan ook aangeboden worden via het besturingssysteem, of ter beschikking gesteld worden via het net. Om nu de 'mismatch' tussen de JDBC aangeboden langs de JAVA applicatie kant, en de ODBC aangeboden langs de DB kant, te kunnen oplossen, moet men beschikken over een JDBC/ODBC bridge.
64
2) native-API partly-JAVA driver (Groen): Deze methode converteert de JDBC calls in de JAVA applicatie naar calls op de API van de specifieke DB. 3) net-protocol all-JAVA driver (Paars): Door deze methode worden de JDBC calls omgezet in een ander DBMS onafhankelijk protocol, die dan omgezet wordt in een DBMS afhankelijk protocol door een server. 4) native-protocol all-JAVA driver (Rood) Deze methode laat toe de DB rechtstreeks en volledig in JAVA aan te spreken met een native DBMS protocol. Deze drivers zullen meestal enkel door de DBMS constructeurs verdeeld worden.
Nadelen: 1) Door het gebruik van ODBC introduceert men terug platformafhankelijkheid op de plaatsen waar deze ODBC code geplaatst wordt. De 'conversie' van JDBC naar ODBC is een extra bron van mogelijke bugs. 2) Ook hier moet er terug native code geplaatst worden op de client machine. ( Bemerk dat de client hier staat voor de client van de database, en dus niet voor de client die inlogt op het systeem!) 3) Deze methode is eerder omslachtig, en lijkt me eerder geschikt om meerdere (verschillende) DB's te kunnen aanspreken. 4) Dit is de beste methode daar ze toelaat de DB volledig in JAVA aan te spreken. Een nadeel is dat deze methode vrij nieuw is, zodat nog niet voor alle DB'en dergelijke drivers beschikbaar zijn. Ook zijn de mogelijkheden nog beperkter dan bij ODBC, maar hierin zal JDBC hoogstwaarschijnlijk ODBC snel bijbenen in de toekomst. Wat wel voor verbetering vatbaar is, is de snelheid. Alhoewel ODBC op dit vlak wellicht altijd zal blijven beter scoren dan JDBC. Daar ik niet beschikte over een DB met JDBC drivers, heb ik gekozen voor de eerste oplossing.
65
5.3 Structuur van de Databank Hier worden de tabellen uit de DB besproken aan de hand van een voorbeeldrij. Indien bepaalde velden voor zich spreken, wordt de uitleg achterwege gelaten. De velden die de primary key bevatten, worden onderlijnd. Alhoewel de types van de verschillende velden meestal uit de voorbeeldrij kunnen afgeleid worden, wordt voor de precieze definitie ervan verwezen naar de ontwerpsweergave van de tabel in MS-Access zelf, omdat deze informatie, alhoewel uiterst belangrijk, detailinformatie is, die niet noodzakelijk is om de tabellen te begrijpen.
5.3.1 Persoon persoonnummer voornaam familienaam straat nummer bus postnummer gemeente 1 Kristof Decloedt Ruitjesb 40 0 8820 Torhout t t land geboortedatum loginnaam paswoord accountnummer België 11/3/75 kdecloedt pas1 000-1234567-000
creatiedatum status 3-2-98 subscribed
Van het accountnummer, dat een banknummer voorstelt, wordt nog geen gebruik gemaakt. Het zou kunnen dienen als de default privé-rekening voor het uitvoeren van niet aangeboden provider services. Ook van het statusveld, dat de bedoeling heeft om (tijdelijk) de toegang van een persoon tot het systeem te kunnen blokkeren, wordt nog geen gebruik gemaakt.
5.3.2 Terminal terminalnummer codenummer 111 10
audio 30
video
terminalnaam 1 thesiscomputer.atlantis.rug.ac.be
Het codenummer stelt het nummer voor van de client software. Dit zal toelaten dat er verschillende client subscription applicaties gemaakt worden, elk met hun specifieke mogelijkheden, of specifiek voor een type terminal. De provider blijft hiervan op de hoogte, en kan mede hierdoor onder andere weten welke services kunnen gedraaid worden op de client. Het audio- en het videoveld bepalen de terminalconfiguratie. Indien ze de waarden 0 toegekend krijgen, is het onmogelijk dat de corresponderende terminal de betreffende vorm
66
van multimedia kan afspelen. Andere waarden kunnen specifieke eigenschappen voorstellen (= fijnere granulariteit). Zo kan de waarde van het videoveld bijvoorbeeld aangeven welke formaten er kunnen afgespeeld worden, of de waarde van het audioveld kan aangeven tot welke frequentie kan of mag afgespeeld worden. De terminalnaam is de naam van de terminal. Hiervoor kan bijvoorbeeld het internet adres opgegeven worden.
5.3.3 Terminalhouders terminalnummer persoonnummer terminalnaam 111 6 thesiscomputer.atlantis.rug.ac.be
5.3.4 Groepen groepnummer naam 9 INTEC
uitleg Alle leden die op
creatiedatum Tue Apr 14 18:38:47
rekeningnummer 001-1234567-89
Het uitlegveld bevat een uitleg die de leden van het veld kunnen opvragen. De gebruikte services worden aangerekend op het rekeningnummer.
5.3.5 Groepleden groepnummer 15
subgroepnummer 17
persoonnummer 12
Deze tabel stelt het ledenbestand van elke groep voor. Het subgroepnummer-veld laat toe de gerichte acyclische graaf ontstaan door het maken van subgroepen, voor te stellen. De volgende figuur zou een dergelijke acyclische graaf met bovenstaand voorbeeld kunnen voorstellen:
67
Alle leden X(12) die via een subgroep B(17) tot de groep A(15) behoren, zullen aanleiding geven tot een (A,B,X) record. X hoeft niet rechtstreeks tot B te behoren, maar kan er via een willekeurig diep geneste subgroep toe behoren. Alle leden worden dus voorgesteld bij alle groepen waarbij ze horen. Dit heeft als grote voordeel dat de databank niet recursief moet ondervraagd worden wanneer men moet weten welke leden tot een bepaalde groep behoren. Dit zal telkens moeten nagegaan worden tijdens het inloggen, of tijdens het opzoeken wat de services zijn die aangeboden worden aan een persoon. Indien men de personen niet allemaal zou voorstellen bij elke groep, dan zou het tijdens het inloggen bijvoorbeeld mogelijk zijn dat een gebruiker geen service aangeboden wordt op de terminal. Hij kan echter deel uitmaken van een groep die dit wel aangeboden krijgt. Zodoende zouden de services moeten nagegaan worden van alle groepen waar de persoon deel van uitmaakt. Indien echter deze groep ook geen services aangeboden krijgt op de terminal, moet men weer alle subgroepen nagaan, enz. Wegens het exponentieel stijgend aantal DB requests, is deze recursieve methode onaanvaardbaar voor de performantie van het subscription systeem, als men weet dat zowel de login procedure als het opvragen van de aangeboden services veelvuldig zulllen voorkomen. Daar de records enkel nummers bevatten, die dus eigenlijk een soort van referenties zijn, zal de extra plaats die hiervoor moet voorzien zijn, in het niets verzinken bij het feit dat men nu in 1 DB request kan nagaan of een persoon tot een bepaalde groep behoort. Dit in plaats van de graaf van groepen recursief te moeten doorlopen, vanaf de desbetreffende groep, tot de knoop (zonder kinderen) die de gezochte persoon voorstelt al dan niet gevonden wordt. Als een persoon X rechtstreeks in een groep A wordt opgenomen, zal een (A,0,X) record worden toegevoegd. Als een groep B in een andere groep A wordt toegevoegd, dan zal (A,B,0) worden toegevoegd. Dit laat toe om tijdens het opvragen enkel de opgenomen groepen en die personen te tonen die rechtstreeks werden opgenomen in de groep. De volgende functies kunnen de toestand van deze tabel wijzigen: addPersoonGroep: Als een persoon met nummer X in de groep A wordt ingevoegd, worden de volgende records gemaakt : (A,0,X), en (B,A,X) als (B,A,0) bestaat. De persoon wordt dus ook in alle groepen gestopt die A bevatten, met als subgroepnummer B. Als men A bekijkt wil dit dus zeggen dat X tot A behoort via subgroep B. addGroepGroep: Als een groep B geïncludeerd wordt als subgroep van groep A, zal er een record (A,B,O) ingevoegd worden. Verder zullen alle leden van de subgroep B bij de bestaande leden van A gevoegd worden: Uit het bestaan van (B,???,X!=0) volgt (A,B,X). 68
wisPersoonUitGroep: Als een persoon X uit een groep B gewist wordt, dan verdwijnen al de volgende records: (B,0,X) en (???,B,X). Deze laatste wist dus de leden ook uit alle groepen waar B deel van uitmaakt. wisGroepUitGroep: Als een groep B uit groep A wordt verwijderd, dan verdwijnen de volgende records: (A,B,???)
Door deze definities is de DB in staat om groepbeheer te doen tot 3 lagen diep in de 'groepen graaf'. Indien men zich beperkt tot het toevoegen of verwijderen van groepen of personen tot de 2 bovenste lagen van de graaf, dan staan er zelfs geen grenzen op de recursiediepte. De reden voor deze beperking is dat tijdens het toevoegen of verwijderen van een groep of persoon in een groep, deze wijzigingen alleen invloed hebben op de groep zelf, en zijn direct omvattende groepen. Om deze lijst van personen die bij elke groep behoort zoals hierboven beschreven werd, consistent te houden, zouden wijzigingen in het ledenbestand van een groep, die een willekeurig diep liggende subgroep is van deze groep, deze lijst moeten aanpassen mocht dit nodig zijn. Als alle functionaliteit op groepen met willekeurig diepe geneste subgroepen moet worden toegelaten, dan bestaan er 3 categorieën van oplossingen:
1) Men laat bovengenoemde optimalisatie vallen, en houdt dus geen dergelijke uitgebreide lijst van personen bij, bij iedere groep. Dit heeft voor gevolg dat de databank bij login en bij opvragen van de services toegekend aan de gebruiker, wel recursief moet opgevraagd worden. Dit is een nadeel, maar moet toch gerelativeerd worden: de recursiediepte zal toch behoorlijk beperkt blijven als men de toepassing bekijkt. Bovendien wordt de recursie hier direct door de mens zelf bepaald, wat nog een reden is waarom zeker geen te diepe structuren moeten verwacht worden. Aanpassingen van het ledenbestand worden nu uitermate eenvoudig: Als een persoon X of een groep B wordt toegevoegd aan of verwijderd uit een andere groep A volstaat het inlassen van een (A,0,X) of (A,B,0) record, of de respectievelijke verwijdering ervan.
2) Het is ook mogelijk dat het ledenbestand van elke groep recursief wordt aangepast bij wijzigingen in een subgroep. Alhoewel dit geen echt performante methode is, kan ze toch als volgt verdedigd worden: Indien men bijvoorbeeld een groep toevoegt of verwijdert uit een andere groep, dan staat dit in feite gelijk met een transactie die in alle groepen die deze groep omvatten een gelijkaardige verandering doet.(met name de betreffende subgroep verwijderen) 69
Of anders gezegd: indien elke gebruiker niet een bestaande groep zou hergebruiken om toe te voegen aan een andere groep, maar deze toe te voegen groep afzonderlijk opnieuw zou aanmaken, dan zouden bij een inhoudelijke (=logische) wijziging van deze toe te voegen groep, ook alle groepen die afzonderlijk gemaakt werden, maar inhoudelijk hetzelfde voorstellen, moeten gewijzigd worden. In feite zouden we dus beter zeggen dat we hier niet in staat zijn om een optimalisatie door te voeren, die toelaat dat al deze groepen ineens worden aangepast. Ondanks dat deze methode het recursiviteitsprobleem enkel lijkt te verschuiven van de procedures die informatie opvragen, naar de procedures die de informatie van het ledenbestand wijzigen, is er toch wel een belangrijke performantiewinst. Normaal gezien zullen de eerstgenoemde procedures veel meer aangeroepen worden dan deze die het ledenbestand aanpassen. Deze methode laat dus onbeperkte recursie toe, dit met een matige performantie, die wel stukken beter is dan de performantie die zou bereikt worden zonder de optimalisatie die recursiviteit bij het opvragen van informatie omzeilt.
3) Er wordt een methode ontwikkeld die toelaat dat de personenlijsten bij elke groep worden aangepast indien nodig, telkens als er personen of groepen worden toegevoegd of verwijderd uit een willekeurig diep geneste subgroep. Dit zou ervoor zorgen dat het gebruik van recursie totaal overbodig wordt. Wellicht is dit op een gelijkaardige wijze mogelijk zoals de recursie gebannen werd tijdens het opvragen van alle personen die (on)rechtstreeks deel uitmaken van een groep, en is wat extra ruimte de oplossing. In appendix B punt 4 werden enkele ideeën gegeven die misschien kunnen gebruikt worden om tot een oplossing van dit recursieprobleem te komen, of die optimalisaties toevoegen aan de recursieve methode.
5.6 Rekening rekeningnummer 001-1234567-89
uitleg Rekening
voor
account INTEC 50500
Het accountveld geeft het bedrag aan waarvoor de groep reeds services geconsumeerd heeft. Dit bedrag moet aangepast worden via een billingsysteem, wat slechts mogelijk is te ontwikkelen eenmaal de link tussen Subscription Management en Session Control voldoende uitgewerkt is. Het uitlegveld wordt als help of info getoond aan de rekening eigenaars, en aan de personen die individueel, dus niet via een groep, een service op deze rekening worden aangeboden.
70
5.7 Rekeninghouders rekeningnummer 001-1234567-89
persoonnummer
rekeningnaam 6 INTEC medewerkers
Het persoonnummer stelt de persoon voor die (mede-) eigenaar is van de rekening in het rekeningnummerveld. In het rekeningnaam veld komt de cryptische omschrijving die deze eigenaar aan de rekening wil geven. Deze wordt getoond aan de eigenaar van de rekening, en aan een persoon die individueel een services werd aangeboden aangerekend op deze rekening, als de 'aanbieder' van een service.
5.8 Service servicenummer naam 1 Video Conferencing
5.9 Gratisservice gratisservicenummer naam 4 UNIC
Het naamveld bevat de naam van de gratis service.
5.10 Grantpersoon persoonnummer terminalnummer servicenummer rekeningnummer rekeningnaam 7 222 2 001-1234567-89 INTEC medewerkers
Persoon 7 wordt op terminalnummer 222 service 2 aangeboden, die zal aangerekend worden op rekeningnummer 001-1234567-89. Er zal hem gemeld worden dat hij deze service aangeboden wordt door 'rekening: INTEC medewerkers'. Dit rekeningnaam veld zal dezelfde naam bevatten als het rekeningnaam veld uit de Rekeninghouders tabel van de persoon die hem het privilege heeft toegekend.
71
5.11 Grantgroep groepnummer 9
terminalnummer 666
servicenummer 3
Groep 9 wordt op de terminal met terminalidentificatie 666 service 3 aangeboden.
5.12 Help caller tekst audio video StandardClientFrame,Help Als u file:/d:/databank/audio/Help.wav http://www.kristof.com/help.mov
In het tekstveld kan de helptekst worden ingetypt. Zowel het audio als het video veld kunnen een willekeurige URL bevatten van het af te spelen mediabestand (eventueel met 'file:/' zoals in de voorbeeldrij).
72
Hoofdstuk 6: Studie over JAVAProgrammeeromgevingen Daar er geen echte enigszins gebruiksvriendelijke JDK programmeeromgeving beschikbaar was, werd er een kleine, maar somtijds moeilijke studie gedaan omtrent de toepasbaarheid voor dit afstudeerwerk, en verder gebruik van enkele van de meest gekende JAVA programmeeromgevingen. Vooreerst dient opgemerkt dat veel informatie komt van producenten zelf, en dat de producten nieuw zijn, zodat hier en daar wel halve waarheden, of slechte interpretaties kunnen voorkomen door al dan niet opzettelijk dubbelzinnige voorstelling van eigen produkten ! Doch, globaal komt het hierop neer:
Verschillende JAVA programmeeromgevingen: Merken: Hierbij gaat het voornamelijk tussen Visual J++ van Microsoft en Jbuilder van Borland. Hier zijn er weinig problemen met het bepalen van de beste: JBuilder blijkt in alle opzichten beter dan Visual J++. Dit komt onder andere omdat de Borland omgeving later is uitgekomen , en beter rekening kon houden met de allerlaatste standaard (jdk 1.1), maar ook wegens verschillende strategische redenen zou Microsoft soms een loopje nemen met de exacte JAVA standaard. (bijvoorbeeld voor het promoten van eigen produkten of standaarden: De combinatie MS Access/ ODBC/Visual basic, OLE, ActiveX e.d. ; of zelfs het toekomstig gevaar dat hun WINDOWS-platform overbodig zou kunnen worden -of minstens aan belang zou moeten inboeten- indien er een JAVA standaard zou komen zonder enige dialect. Sun zou hiervoor een speciale chip ontwerpen die JAVA bytecode rechtstreeks kan uitvoeren!)
73
Keuze tussen de verchillende produkten van Borland: (rekening houdende dat MS Access als “background”databank wordt gebruikt) JBuilder Standard : Dit lijkt me een soort ‘speelgoedversie’ te zijn voor het maken van leuke applets voor het internet. Hier is geen toegang voor databanken voorzien, en deze versie zou dus uitgesloten zijn om te gebruiken voor een degelijk programma.
Jbuilder Professional : Hier is wel de mogelijkheid tot toegang tot databanken voorzien via JDBC. Om met deze versie op een Windows NT platform effectief een connectie op te zetten, is er enkel ofwel een JDBC-driver ofwel een ODBC-driver nodig, naargelang de keuze die gemaakt is omtrent de methode om de DB aan te spreken (zie hoofdstuk 5) Een (gratis) MS-Access JDBC driver heb ik nergens kunnen vinden, tenzij in een trialversie van Borlands datagateway. Een MS-Access ODBC driver wordt meegeleverd met MSAccess zelf.
Jbuilder Client/server : Deze versie bevat de professional versie, plus de datagateway (= bevat vele JDBC-drivers: onder andere die voor MS-ACCESS), plus nog enkele andere tools, waaronder Visigenic CORBA ondersteuning.
74
Appendix A : Historiek September: Hier werd begonnen met het lezen van de TINA specificaties. Daar de precieze inhoud van het afstudeerwerk nog niet was vastgelegd, werden alle TINA onderdelen doorgenomen. Verder werd ook CORBA voor C (Orbix) bestudeerd.
Halfweg oktober: Omdat er overgeschakeld werd van C naar JAVA werd hier vooral tijd gestopt in het herstuderen van CORBA, maar nu voor JAVA. Daar JAVA voor mij nog geen gekende taal was, werd ook deze doorgenomen. Rond deze tijd werd ook begonnen met de installatie van Windows NT. Dit leverde wat problemen op met het NTFS. (zie Appendix C: Tijdsbesparende tips) Daar er geen JAVA programmeeromgeving voor handen was, tenzij een niet echt gebruiksvriendelijke JDK commandline versie van SUN, werd hier een kleine studie gedaan omtrent de verschillende JAVA programmeeromgevingen die op de markt waren, en die zouden kunnen gebruikt worden voor enerzijds de verschillende thesisstudenten, en anderzijds de medewerkers die werkten met JAVA. Zie hoofdstuk 6 voor een korte bespreking hierover.
November: Er werd aanvang genomen met het ontwerpen van het systeem op papier. Daar ik vrij snel het besluit nam om een bestaande database te gebruiken, werd nagegaan welke databanken hiervoor best geschikt waren en welke methodes er voor het aanspreken het best gebruikt werden. Deze studie was verweven met de vorige, en werd ook beïnvloed door de beschikbaarheid van de verschillende stukken software. Voor een bespreking zie Hoofdstuk 6. Samenhangend met deze studies, moest ook gezocht worden naar de nodige software.
75
December: De TINA specificaties, OrbixWeb en JAVA waren nu grondig doorgenomen, en Windows NT was tezamen met Windows 95 geïnstalleerd. Hier had ik echter een eerder langdurend probleem om Orbix draaiende te krijgen onder NT. (zie Appendix B: Tijdsbesparende tips)
Januari: Volgens menige opinie was het mogelijk om Windows te laten geloven dat er een netwerkkaart aanwezig is, zonder dat dit fysisch het geval is. Ik meen dat Windows 95 en Windows NT hier door elkaar werden gehaald. Dit werd getest met een kaart die me door INTEC ter beschikking werd gesteld. Hierdoor draaide het volledige systeem perfect en kon nu begonnen worden met het effectief programmeren. … Examens …
Halfweg februari: Hier volgden 2 weken programmeerwerk, wat resulteerde in de implementatie van de Manager.
Maart: Ook de andere servers werden geïmplementeerd alsook de client.
Half April: Overleg met diegenen die het Service deel van het systeem implementeerden, om geen hypotheek te leggen op een toekomstige vereniging van beide werken.
Mei: Een eerste versie van het programma is af, en wordt mede als test, op een PC van INTEC gezet, en voorgelegd aan de thesisbegeleider. Het programma wordt nog verder getest. Een stuk ontbrekende code wordt ingevuld, en kleinere fouten worden verbeterd. Daar het programma nu zo goed als af was, kon het schrijven beginnen.
76
Half mei: Een eerste versie van de scriptie wordt afgegeven aan de begeleider. De proef- en echte verdediging vinden plaats.
Juni: De scriptie wordt afgegeven.
77
Appendix B : Uitbreidingen en Verbeteringen 1. Inleiding Alhoewel het mooi zou ogen om hier een lijst van veelbelovende idl interfaces te geven, zal ik er me niet toe laten verleiden. Het zou immers al te eenvoudig zijn om alle mogelijke wensen waaraan een systeem moet voldoen te vertalen in idl, en deze dan te vermengen met de werkelijk geïmplementeerde interfaces. Dit zou niet alleen misleidend zijn voor de effectieve prestatie van het afstudeerwerk, maar bovendien ook nutteloos als dit niet gebeurt in overleg met diegene(n) die ze moeten implementeren. Bij een theoretische beschouwing zou de idl inderdaad niet echt mogen beïnvloed worden door zulke implementatie overwegingen, maar bij de praktische implementatie van deze theoretische interfaces, zal dit meestal enigszins anders liggen. Tenslotte zou dit werk juist het tegengestelde zijn van wat er gevraagd werd in deze thesis: het realiseren van een concrete toepassing die (zoveel mogelijk) voldoet aan de bestaande theoretische achtergrond. Daarom heb ik besloten om verbeteringen en uitbreidingen ten eerste enkel te suggereren in tekstuele vorm, waaruit men dan later de interfaces kan destilleren, die in de praktijk haalbaar zijn volgens die middelen die men ter beschikking heeft. Dit maakt het overbodig dat men eerst de achterliggende gedachte van de gegeven interfaces moeten achterhalen, vooraleer men ze bijvoorbeeld kan aanpassen voor specifieke noden of beschikbare middelen. Door de uitbreidingen direct in tekstuele vorm te geven, slaat men hier dus in feite de 'reverse engineering'- stap over. Ten tweede zullen enkel voorstellen gedaan worden die direct aansluiten bij de reeds bestaande code, en die dus zonder veel extra ontwerp kunnen worden uitgevoerd. Dit laat de mensen die onderdelen schrijven die nu nog niet aangeraakt zijn, toe om creatief te zijn, en deze onderdelen volledig te ontwerpen naar eigen goeddunken. Dit kan alleen maar de kwaliteit van het afgeleverde programma ten goede komen.
78
2. De Client 1) De bestaande menu's voor het wissen van privileges kan nog uitgebreid worden, zodat, wanneer op eender welke selecteertoets gedrukt wordt, de inhoud van de getoonde lijsten gefilterd wordt met de reeds ingevulde tekstvelden. Wanneer er bijvoorbeeld een persoon geselecteerd wordt, is het overbodig om in een terminallijst alle terminals te tonen waarvan de gebruiker eigenaar is. Enkel die terminals waarop aan de geselecteerde persoon een service is toegekend, is hier voldoende.
2) Daar nu duidelijk geworden is welke van beide lay-out methodes het best is, zou deze in een echte LayoutManager kunnen gegoten worden. De 'hardgecodeerde' LayoutManagers in elk van de menu's, zouden dan door deze LayoutManager kunnen vervangen worden.
3) Het optie menu zou nog kunnen uitgebreid worden om service profile parameters in te vullen. Dit vereist natuurlijk dat deze profiles ook langs de providerzijde ondersteund worden.
4) De interface naar de UA kan nog ontworpen en ingevuld worden. Deze zou het mogelijk moeten maken dat: - de provider op regelmatige tijdstippen kan nagaan of de client niet onverwacht is afgesloten (zonder dat er een clientShutDown is gebeurd). Dit is nodig met het huidige ontwerp, omdat bij een client crash, deze client op de betreffende terminal niet zal uitgelogd zijn, waardoor de UCxt hem zal beletten om nog op dezelfde terminal opnieuw in te loggen. - de client zou kunnen uitgenodigd worden om aan een sessie deel te nemen. Dit vereist natuurlijk overeenkomstige aanpassingen van de UA en/of de Session Control, naargelang het ontwerp.
79
3. De Provider 1) Databank: MS Access zou kunnen vervangen worden door een meer performante databank. Ook zou met de tijd kunnen overwogen worden of een ODBMS niet beter geschikt is.
2) De werkelijke implementatie van de interface die de UA aanbiedt aan de client, zou kunnen verplaatst worden van de UA zelf naar die componenten die hier echt voor dienen.(zoals dit nu reeds onder andere gebeurd is voor providerServices, gratisProviderServices of mijnGroepen.
3) De SubRg kan ontworpen worden. Dit heeft, zoals reeds vermeld in hoofdstuk 3, enkel zin als er enkele services aangeboden worden.
4) Een weinig dringende verandering zou erin bestaan om de frontend van de DB te vervangen door een eigen frontend.
5) Daar de Manager de eerst geschreven server is, is de kwaliteit van zijn code wellicht het laagst. Alhoewel niet noodzakelijk, zou deze code eventueel kunnen herwerkt worden.
6) Het is mogelijk om groepen van personen te maken. Zo kan men een privilege toekennen aan een ganse groep ineens, in plaats van dit afzonderlijk te moeten doen voor alle personen individueel. Nu zou een uitbreiding erin bestaan om hetzelfde te doen met terminals. Deze zouden ook kunnen worden gegroepeerd, zodat een individuele persoon of een groep een privilege kan worden toegekend op een volledige groep terminals ineens.
7) Het zou moeten mogelijk zijn om de code van de client dynamisch te laden als er een nieuwe versie beschikbaar is.
8) De terminalconfiguratie bevindt zich nu vast in de databank. In de toekomst zou deze configuratie als een bestandje op de client moeten staan. Bij inloggen zou dan kunnen nagegaan worden of deze configuratie veranderd is.
80
9) Nu is het nog niet mogelijk dat het ledenbestand aangepast wordt van groepen die zich niet in de hoogste 2 lagen van de 'subgroepen-graaf' bevinden. Hiervoor zouden de voorstellen uit punt 4 kunnen gebruikt worden.
10) Eenmaal de UA is aangemaakt door de UAF, blijft hij op dit ogenblik 'eeuwig' leven. Het zou een kleine maar nuttige verbetering zijn om de UA uit te schakelen als de gebruiker gedurende een welbepaalde tijd niet meer is ingelogd op het systeem. Hiervoor kan de UCxt, die een lijst bijhoudt van de terminals waarop de gebruiker is ingelogd, een bericht zenden naar de UAF wanneer de gebruiker is uitgelogd op de laatste terminal. Als reactie zou de UAF een timer kunnen starten die na een zekere tijd een signaal teruggeeft. Indien er intussen geen nieuwe inlogprocedure gestart is door die gebruiker, wordt zijn UA verwijderd. Dit levert geen problemen op aangezien alle informatie van de betreffende gebruiker zich in de DB bevindt.
11) De terminalidentificatie die nu als commandline parameter meegegeven wordt, zou moeten vervangen worden door iets wat niet te vervalsen is, zoals een machine of een PIN nummer. Indien een IP-adres kan geverifieerd worden, kan ook dit nummer gebruikt worden.
12) In de UCxt zou naast de wis-functie ook nog een suspending-functie moeten gemaakt worden die toelaat een sessie tijdelijk af te breken in plaats van definitief uit te loggen. Dit zou gemakkelijker terminal mobility toelaten (zie Appendix B)
4. Denkpistes voor aanpassing Groepleden tabel Hier staan enkele losse ideeën die misschien kunnen leiden tot een methode die de aanpassing van het ledenbestand tot op willekeurige diepte toelaat. Er wordt zeer sterk benadrukt dat dit enkel snel ontsproten ideeën zijn, die bijgevolg verre van gegarandeerd foutvrij zijn! Indien een van deze ideeën echter kan leiden tot een oplossing van het probleem, is hun opzet geslaagd. A) Nu worden in elke groep alle personen bijgehouden die er eventueel via een willekeurig diep geneste subgroep toe behoren. Dit laat toe recursie te bannen als nagegaan moet worden of een persoon tot een groep behoort. Identiek hetzelfde principe kan nu worden toegepast
81
met de subgroepen van een groep, wat tot identiek hetzelfde resultaat zal leiden: bannen van recursie bij het manipuleren van het ledenbestand. Er moet een extra 'reference count' kolom worden ingevoegd in de Ledenbestand tabel, die voor de huidige records 0 zal zijn. Naast deze bestaande records, moeten er in deze tabel ook nieuwe 'node records' komen. Dit zijn records die de subgroepen van een groep tot op willekeurige diepte voorstellen. In het groepnummer veld wordt het groepnummer ingevuld van de groep waartoe ze behoren. Het subgroepnummer veld dient om het groepnummer van de willekeurig diep geneste subgroep in te vullen. Het persoonnummer veld=0. Het nieuwe 'reference count' veld van dit 'node record' bevat het aantal wijzen waarop deze subgroep behoort tot de groep. Dit kan mogelijk op meerdere wijzen door overlap van het ledenbestand: 2 groepen die een zelfde subgroep hebben, kunnen op hun beurt deel uitmaken van eenzelfde groep. Telkens een groep C toegevoegd wordt aan een andere groep B, worden de reference count velden van de node records van de nieuwe subgroep C opgeteld bij de omvattende groep B. In 1 DB request kan (omdat deze node records bijhouden welke subgroepen een groep bevat tot op willekeurige diepte) nagegaan worden van welke groepen A de omvattende groep B een subgroep is (ook op willekeurige diepte). Bij al deze groepen A worden de node records van de nieuwe subgroep C bijgeteld, na vermenigvuldiging met het aantal keer dat de subgroep B voorkomt in de groep A. (Dit aantal wordt juist gehaald uit hun reference count field). Indien een record voor een bepaalde groep nog niet bestaat, wordt hij nieuw aangemaakt. De vermenigvuldiging is nodig omdat een groep A op x verschillende wijzen (= verschillende paden) de subgroep B kan bevatten. Op zijn beurt bevat de subgroep B, y keren een groep D bepaald door de node records van de nieuwe subgroep C. Met andere woorden, de groep A zal op xy nieuwe wijzen de groepen D uit C bevatten. Naast het aanpassen van de reference count fields, moeten ook de personen die deel uitmaakten van de subgroep in de groep worden opgenomen. Bij het verwijderen van een groep, kan men op dezelfde wijze tewerk gaan. Als de reference count van een groep 0 wordt, moeten de personen verwijderd worden. Om een persoon toe te voegen aan een groep, gaat men in 1 DB request na welke groepen deze groep als subgroep (op willekeurige diepte) bevatten. De persoon kan dan toegevoegd worden aan al deze groepen . Hetzelfde geldt voor het verwijderen van een persoon uit een groep. Probleem met deze methode is dat men niet direct kan nagaan via welke subgroep een persoon deel uitmaakt van de groep. Dit is wellicht op te lossen door nog een extra kolom.
82
B) Andere ideeën zijn: Personen toevoegen en verwijderen: 1) Men kan recursief de omvattende groepen doorlopen en opnieuw construeren op basis van de subgroepen. Zoals hierboven uiteengezet, is deze recursiviteit sterk af te raden, alhoewel de zaken hier enigszins anders liggen: Het gaat hier niet louter om het opvragen van informatie, maar om het aanpassen ervan, en vanuit het oogpunt van de informatie die hier veranderd wordt, ziet men dat inderdaad de informatie van alle groepen die de betreffende persoon via een (of meerdere) subgroep(en) bevat(ten), gewijzigd wordt. Vanuit dit standpunt heeft men dus niet echt een overhead, wat natuurlijk niet belet dat de performantie slecht is.
2) Men kan een extra kolom maken die het groepnummer aangeeft waar de persoon in toegevoegd werd. Deze kolom zou men eindgroepnummer kunnen noemen. Deze kolom is volledig analoog aan de subgroep kolom. In de plaats dat men nu naar beneden in de gerichte graaf kan kijken (van groep naar subgroepen), kan men nu ook naar boven kijken, van persoon naar alle groepen die deze persoon (on)rechtstreeks bevatten. Het zou bij addPersoonGroep dus volstaan om (A,0,0,X), en (B,C,A,X) mits (B,C,A,???) bestaat toe te voegen in plaats van (A,0,X) en (B,A,X) als (B,A,0) bestaat. De persoon X wordt dus toegevoegd aan de groep A zelf, en aan alle groepen B die reeds een lid ??? bevatten van de desbetreffende groep A. De reden hierachter is dat als er een persoon ??? kan gevonden worden, die direct lid is van groep A en hierdoor indirect via een willekeurig pad van subgroepen lid is van B (via C), dat dit laatste dan ook zal gelden voor elk nieuw lid van A. Analoog voor het verwijderen van een persoon. Voorwaarde is wel dat er in iedere groep reeds een persoon aanwezig is, vooraleer men deze toevoegt in een andere groep. Deze voorwaarde kan men voor de gebruiker laten wegvallen, als men zelf tijdens de creatie van een groep, direct een dummy persoon toevoegt. Deze methode zou dus zeer eenvoudig zijn, en zou recursie overbodig maken. Nadeel is dat er extra ruimte nodig is voor een extra kolom, en ook voor een extra aantal rijen. (Indien er overlap is tussen de verschillende groepen. Met overlap wordt bedoeld: als een persoon via meerdere subgroepen tot dezelfde groep behoort.)
83
Groepen toevoegen bij en verwijderen uit andere groepen: De situatie hier ligt niet zo eenvoudig als bij het toevoegen en verwijderen van personen. Als de groepenstructuur wordt voorgesteld door een acyclisch gerichte graaf, dan stellen de knopen de groepen voor, en de bladeren de personen.
1) Wel, als men hier niet recursief wil werken, dan moet men in iedere knoop niet alleen bijhouden welke bladeren die knoop heeft, eventueel via een aantal kindknopen, maar ook via welke knopen men elk blad bereikt. Als men immers een knoop verwijdert, moet men weten welke bladeren voor de ouderknopen zichtbaar blijven en welke er verdwijnen. Omdat personen tot verschillende groepen kunnen behoren, die op hun beurt deel kunnen uitmaken van dezelfde groep (zie figuur hoofdstuk 5, p67), is het niet noodzakelijk zo dat alle bladen van de verwijderde knoop, ook onzichtbaar worden voor zijn parentknopen! Het bijhouden van een pad van iedere knoop tot elk blad, kan op 2 wijzen gebeuren: ofwel maakt men een aantal extra kolommen waar tussenknopen kunnen worden ingevuld, ofwel codeert men dit in een aantal rijen. De eerste methode kan niet, daar ze weer een beperking zal opleggen aan de recursiediepte, die gelijk zal zijn aan het aantal extra gereserveerde kolommen, en de tweede methode zal ten eerste een extra kolom vergen, ten tweede de lengte van de tabel doen toenemen met de gemiddelde padlengte van knoop naar blad, en zal dan ten derde toch nog 2 DB requests vragen: een eerste om na te gaan welke knopen zullen moeten worden aangepast (namelijk deze die een blad bevatten dat op het pad ligt met de verwijderde knoop), en een tweede om alle records te verwijderen die dit pad voorstellen. Beide methodes om dit pad bij te houden zijn verre van ideaal.
2) Een tweede methode bestaat er terug in recursief te werken. Alhoewel dit geen echt performante methode is, kan ze toch als volgt verdedigd worden: Indien men een groep toevoegt of verwijdert uit een andere groep, dan staat dit in feite gelijk met een transactie die in alle groepen die deze groep omvatten een gelijkaardige verandering doet. Of anders gezegd: indien elke gebruiker niet de bestaande groep zou hergebruiken om toe te voegen aan een andere groep, maar deze toe te voegen groep zelf opnieuw zou aanmaken, dan zouden bij een inhoudelijke wijziging van deze toe te voegen groep, ook alle groepen die afzonderlijk gemaakt werden, maar inhoudelijk hetzelfde voorstellen, moeten gewijzigd worden. In feite zouden we dus beter zeggen dat we hier niet in staat zijn om een optimalisatie door te voeren, die toelaat dat al deze groepen ineens worden aangepast.
84
Deze methode bestaat er dus in om met een DB query alle groepen op te zoeken die de gewijzigde groep bevatten. Deze groepen moeten dan opnieuw worden samengesteld uit hun ledenbestand. Een addertje onder het gras bij deze methode is het gevaar van overlap van verschillende groepen, zodat een systeem van markering zou nodig zijn: Het is immers mogelijk dat een groep opnieuw wordt samengesteld, en dat pas daarna een van de groepen waaruit hij is samengesteld, wordt aangepast. Daarom is het misschien aangewezen om bij deze recursieve methode een systeem van 'referential counts' te gebruiken, dat geïnspireerd is op principes van garbage collection. Hiervoor zou er een extra kolom moeten gemaakt worden die bij iedere record telt hoeveel maal de persoon via de hierboven voorgestelde eindgroepnummer kolom geïncludeerd wordt. Indien groep B toegevoegd wordt aan groep A, zal record (B,???,C,X,R) met R de referential count en C,X,R willekeurig, aanleiding geven tot het nieuwe record (A,B,C,X,R). Nu zal men in alle omvattende groepen F het record (F,A,C,X,R1) aanpassen tot (F,A,C,X,R1+R2), met R2 het getal waarmee R uit A vermeerderd is. Dit laatste dient recursief te gebeuren voor alle omvattende groepen. Als groep B wordt verwijderd uit groep A, moet men nu vanaf de gewijzigde groep telkens recursief naar de omvattende groepen gaan, en daar de referential count verminderen met het getal waarmee de referential count van de subgroep verminderd werd. Indien dit count-field hierdoor op 0 wordt gezet, wil dit zeggen dat de betreffende persoon niet meer te bereiken valt via deze subgroep. Dit record mag dan ook verwijderd worden. Met andere woorden: als groep B verwijderd wordt uit groep A, dan zal (A,B,0,0,0) dus verwijderd worden tezamen met (A,B,C,X,R) met R de referential count en C,X,R willekeurig. In alle groepen F die A omvatten zullen de records (F,A,C,X,R1) aangepast worden tot (F,A,C,X,R1-R2), met R2 het getal waarmee R verminderd is. Indien R1-R=0, dan zal het volledige record wegvallen. Dit laatste zal nu recursief in de F omvattende groepen verder doorgevoerd worden. Deze methode komt er dus op neer dat men de leden van de subgroepen toevoegt aan of verwijdert van de omvattende groep, wat dus nu reeds geïmplementeerd is (zij het dat men in de SQL instructies wel beide nieuwe kolommen moet invullen). Wat nieuw is, is dat een extra lus nodig is om de recursie te implementeren die de reference counts in de omvattende groepen aanpast: optellen voor groepen bijvoegen, aftrekken om groepen te verwijderen, en die als de reference count op 0 komt, het record verwijdert. Nog een andere methode zou erin bestaan om het subgroepnummer van de 'dummy personen' hierboven besproken bij het toevoegen en verwijderen van personen, te gebruiken als reference count field. Deze records laten zien op hoeveel wijzen een groep vervat zit in een 85
andere groep. Hiervoor moet telkens er een groep aangemaakt wordt, of een groep in een andere groep toegevoegd of verwijderd wordt, de count fields van de 'dummy persoon' records aangepast worden. Door recursief de omvattende groepen te doorlopen, en deze opnieuw samen te stellen op basis van de groepen en personen die ze direct bevatten, wordt het geheel consistent. Deze 'dummy persoon' kan ook gezien worden als een record dat bijhoudt hoeveel keer een subgroep, op gelijk welke diepte, geïncludeerd werd in een groep. Voor iedere groep die (on)rechtstreeks deel uitmaakt van een andere groep, bestaat er zo'n record.
Deze methoden vullen dus eerder de bestaande code aan dan ze te veranderen. Verder moet het performantieverlies door de recursie, om reeds eerder vermelde reden gerelativeerd worden, maar ook omdat de recursiediepte toch behoorlijk beperkt zal blijven als men de toepassing bekijkt waarvoor ze hier gebruikt wordt. Bovendien wordt de recursie hier direct door de mens zelf bepaald, wat nog een reden is waarom zeker geen te diepe structuren moeten verwacht worden.
Er wordt nogmaals op gewezen dat omzichtig moet worden omgesprongen met deze ideeën, dit is trouwens de reden waarom ze te vinden zijn in een appendix. Verder zijn er wellicht nog tal van andere (betere) oplossingen mogelijk.
86
Appendix C : Tijdsbesparende tips Deze tips zijn een samenraapsel van problemen die me soms veel tijd hebben gekost om op te lossen, en die mensen die verder werken op dit afstudeerwerk misschien veel tijd zouden kunnen besparen:
1) Om OrbixWeb te kunnen draaien, is het in Windows 95 niet nodig om effectief een netwerkkaart te hebben. Indien je bijvoorbeeld een kaart installeert, en je verwijdert ze daarna, zal Windows 95 niet protesteren, maar nog altijd denken dat de kaart aanwezig is. Anders is het gesteld bij Windows NT. Mij is het niet gelukt om het systeem te laten werken zonder netwerkkaart. Ik ben redelijk overtuigd dat het gewoon niet kan: Windows NT werkte niet zonder netwerkkaart, dan direct wel met kaart, en toen ik ze er terug uithaalde, zonder iets aan de instellingen te wijzigen, weer niet. Ook niet wanneer ik een en ander in deze instellingen afzette. (zie historiek)
2) Indien Windows NT gebruikt wordt, met release 3 erop geïnstalleerd, zal de Orbix Deamon niet goed draaien, als je de noodzakelijke netwerkkaart installeert. Het programma zal runnen, maar uitermate traag. (een 50 tal seconden per connectie). Ondanks dat er tijdens de installatie van de netwerkkaart er zich geen problemen hoeven voor te doen, of dat er geen fout of waarschuwingsmeldingen komen, zal Windows NT niet goed draaien, zolang de service pack niet opnieuw geïnstalleerd is. Deze installatie moet telkens opnieuw overgedaan worden (bovenop de oude installatie), als je iets aan de instellingen verandert, zodat je de originele Windows NT CD nodig hebt.
3) Service Pack 3 van Windows NT biedt betere ondersteuning voor ODBC. Wat echter niet vermeld wordt, is dat sommige bestanden op verkeerde plaatsen worden gekopieerd, zodat de databank juist niet kan aangesproken worden. Daarom moet je uit de foutmelding destilleren om welk bestand het gaat. Dit bestand zal 2 x voorkomen in de WINDOWS directory, op 2 verschillende plaatsen, beide met een andere datum. Kopieer de nieuwe versie op de plaats waar de oude staat (en overschrijf hem dus).
87
4) In de Orbix configuratie kon bij mij in het CLASSPATH geen '\' ingetikt worden. Open daarom gewoon het Orbix.cfg tekst bestand dat zich in de orbix directory bevindt: dit bestand bevat alle gegevens die in de orbix configuratie worden getoond. Aanpassingen aan dit bestand zijn eenvoudig.
5) Het classpath kan op 3 plaatsen ingegeven worden: in een batch bestand, in het Orbix configuratie bestand, of in de systeem parameters van Windows NT. De client zal gebruik maken van het classpath, en het path zoals die zichtbaar zijn in de DOS omgeving: een combinatie dus van de inhoud van een 'start batch bestand' of de commandline parameters, en de systeem parameters. De Orbix Deamon daarentegen, zal gebruik maken van de combinatie systeemparameters en Orbix Config bestand. Dit vormt natuurlijk geen probleem als het CLASSPATH in de systeem parameters van Windows NT, of bij Windows 95 in de autoexec.bat of orbwebvars.bat van Orbix, alle mogelijke paden bevat die nodig zijn voor de client en de servers. Dit lijkt me echter nogal grof, en getuigt niet van veel inzicht in het hoe en waarom van wat je doet.
6) Indien ervoor gekozen wordt om Windows NT te gebruiken, en dit systeem wordt geïnstalleerd met NTFS, is het niet eenvoudig om NTFS alsnog te veranderen in FAT. Hiervoor moet de harde schijf opnieuw geformatteerd worden, en dit is juist het probleem. * Windows NT zelf wil de partitie niet formatteren waar hij zelf opstaat. * Vanuit een ander systeem dat op de HD kan staan, zoals Windows 95, is deze NTFS partitie onzichtbaar. * Noch met de opstartdiskettes van Windows 95, noch met de opstartdiskettes van Windows NT kan iets aangevangen worden. * fdisk van beide systemen laat het afweten. … Als uiteindelijke remedie vond ik om een oude DOS 6.00 (of vroeger) diskette vanonder het stof te halen, en daarmee op te starten. Hiermee zal wel een fdisk kunnen uitgevoerd worden.
7) Indien besloten wordt om Windows 95 te gebruiken, dan ontstaan er gegarandeerd 'out of environment space' problemen tijdens het uitvoeren van een batch bestand dat waarden toekent aan omgevingsvariabelen. Een oplossing hiervoor is om in de commandline parameter tekstbox van een Windows shortcut, of in de DOS prompt 'command /e:20000' in te tikken. 88
8)Indien het volledige afstudeerwerk op een andere PC met Windows NT wordt geplaatst, is het niet noodzakelijk, maar wel het best dat telkens ingelogd wordt met Administrator privileges. Zo zullen alle geregistreerde servers in de implementation register van Orbix zeker ten allen tijde bewerkbaar zijn.
89
Appendix D : CD-ROM Inhoud: \Root directory Register_Servers.bat : Het batch bestand dat de provider servers registreert en waarin de eerste regels aangepast moeten worden, om bijvoorbeeld aan te geven waar de gebruikte JDK zich bevindt. Opgemerkt moet worden dat deze JDK zeker de SQL en de Thread packages moet bevatten.
\Thesis\ Idl:
Bevat het bestand met de idl interfaces. Deze werden door Compile.bat gecompileerd naar de java_output subdirectory.
projecten:
Bevat de java source code van dit afstudeerwerk
MediaPlayer: Deze directory bevat in tegenstelling tot het stub-bestand in de package thesis.reuse in de directory "Thesis\projecten", de echte MediaPlayer code. Deze code kan niet gecompileerd worden via JBuilder omdat de sourcecode van gebruikte JMF classes niet beschikbaar is. Bijgevolg moeten de classbestanden van deze MediaPlayer gegenereerd worden via de commandline. Hiervoor moet het batch bestand gojb.bat uitgevoerd worden.
commandline: Deze directory bevat de bestanden die moeten gekopieerd worden bij de classes gegenereerd na een nieuwe compilatie van de java code. Deze bestanden bestaan uit het batch bestand om de client op te starten, uit images als achtergrond en voor de imagebuttons, en tenslotte ook uit de MediaPlayer class bestanden die een kopie zijn van de class bestanden uit de directory "Thesis\MediaPlayer". 90
Yoeri_Sophie: Daar de "Session Control Thesis" kan opgeroepen worden vanuit mijn afstudeerwerk, zijn de gecompileerde interfaces van deze eerste nodig. Deze werden tezamen met de volledige JAVA broncode van een van de laatste versies, in deze directory geplaatst, alsook de bijhorende idl bestanden en enkele opgeslagen figuren. Zodoende kan dit volledige afstudeerwerk gecompileerd worden vanuit JBuilder, zodat het naast het testvoorbeeldje van "Grafische transformaties" als een voorbeeld van een service kan gestart worden.
\classes\ - Bevat de interpreteerbare code van de client, de provider, alsook in package White een van de laatste versies van de WhiteBoard service. - In deze directory werden reeds de bestanden uit de commandline directory gekopieerd.
\Databank\ databank.mbd : Bevat een voorbeeld MS Access databank
Audio
: Bevat de audio bestanden die kunnen afgespeeld worden als helpinformatie.
Foto
: Bevat alle images die ergens gebruikt worden (bij de client, de manager, of in de reuse package )
Video
: Bevat enkele demo video bestanden die kunnen afgespeeld worden tijdens het opvragen van helpinformatie over een onderwerp, of als help bij een reclame service.
91
\external_classes\ Bevat classes die nodig zijn om de client en de provider te kunnen uitvoeren. Dit zijn de JBuilder classes, die enkel gebruikt worden voor de logintekstbox en de image button bar.
\JMF\ Deze directory bevat de bestanden van de JMF (Java Media Framework) bètaversie. Ze worden gebruikt door de MediaPlayer.
\thesis_boek\ Deze directory bevat alle bestanden die gebruikt werden in dit boek.
92
Universiteit Gent Faculteit Toegepaste Wetenschappen
Vakgroep Informatietechnologie Voorzitter: Prof. Dr. Ir. Lagasse
TINA gebaseerd Subscription Management door Kristof DECLOEDT DEEL ΙΙ
Promotor: Prof. Dr. Ir. P. DEMEESTER Thesisbegeleider: Ir. F. VANDERMEULEN
Afstudeerwerk ingediend tot het behalen van de academische graad van burgerlijk ingenieur computerwetenschappen Academiejaar 1997-1998
TINA gebaseerd Subscription Management door Kristof DECLOEDT DEEL ΙΙ
Afstudeerwerk ingediend tot het behalen van de academische graad van burgerlijk ingenieur computerwetenschappen Academiejaar 1997-1998 Promotor: Prof. Dr. Ir. P. DEMEESTER Thesisbegeleider: Ir. F. VANDERMEULEN Faculteit Toegepaste Wetenschappen Universiteit Gent Vakgroep Informatietechnologie Voorzitter: Prof. Dr. Ir. Lagasse
Samenvatting Deel ΙΙ bevat de IDL interfaces en de Java code van de software besproken in Deel Ι. Deze worden voorafgegaan door een aantal korte opmerkingen
II
Voorafgaande opmerkingen: * Volgende notatie werd zoveel als mogelijk consequent toegepast: - IDL interfaces : Deelwoorden gescheiden door '_' Volledig in kleine letters Eindigen op '_if' - Java functies : Deelwoorden aan elkaar Eerste woord beginnend met kleine letter, de volgende met hoofdletter - Java variabelen : Zelfde stijl als functies. Het onderscheid ermee kan gemaakt worden omdat hier geen haakjes volgen. - Java Klassen : Deelwoorden aan elkaar Alle deelwoorden beginnen met een hoofdletter - Constanten : Deelwoorden aan elkaar Volledig in hoofdletters Ook de databank parameters worden hieronder begrepen. - Databank tabellen : Deelwoorden aan elkaar Alleen de eerste letter van het eerste deelwoord is een hoofdletter - Databank kolomnamen : Deelwoorden aan elkaar volledig in kleine letters
* Omdat deze software nog verder moet worden uitgebouwd, werden er meer 'try…catch' blokken gebruikt dan strikt noodzakelijk. Dit zal leiden tot een gemakkelijker precieze lokalisatie van fouten tijdens deze verdere ontwikkeling.
Toelating tot bruikleen "De auteur geeft de toelating dit afstudeerwerk voor consultatie beschikbaar te stellen en delen van het afstudeerwerk te copiëren voor persoonlijk gebruik. Elk ander gebruik valt onder de beperkingen van het auteursrecht, in het bijzonder met betrekking tot de verplichting de bron uitdrukkelijk te vermelden bij het aanhalen van resultaten uit dit afstudeerwerk." 1998-05-09
III
Inhoudstafel: 1 IDL Interfaces 2 Source Code 2.1 Manager 2.2 Welcome 2.3 User Agent 2.4 User Context 4.5 Subscription Agent 2.6 Service Template Handler 2.7 Subscriber Manager 2.8 Subscription Registrar 2.9 Software Reuse 2.10 Service Demo 2.11 End User Application
IV
1
//****************************************************************************** // IDL Interfaces //******************************************************************************
module types{ //mijnServices struct mijn_services_nummer_naam_struct{ string nummer; //van de rekening string naam; //van de rekening string groep_uitleg; //uitleg over groep }; struct mijn_services_struct{ long service_nummer; string service_naam; sequence<mijn_services_nummer_naam_struct> rekening; boolean uitvoerbaar; }; typedef sequence<mijn_services_struct> mijn_services_useq;
//getHelp struct help_struct{ string tekst; string audio; string video; };
//mijnGroepen struct mijn_groepen_struct{ long nummer; //van de groep string naam; //van de groep string uitleg; //uitleg over de groep }; typedef sequence<mijn_groepen_struct> mijn_groepen_useq;
//providerServices struct provider_services_struct{ long nummer; //van de service string naam; //van de service }; typedef sequence<provider_services_struct> provider_services_useq;
//gratisProviderServices struct gratis_provider_services_struct{ long nummer; //van de service string naam; //van de service }; typedef sequence
gratis_provider_services_useq;
//mijnTerminals struct mijn_terminals_struct{ long nummer; //van de terminal string naam; //van de terminal }; typedef sequence<mijn_terminals_struct> mijn_terminals_useq;
//mijnRekeningen en toonRekening struct mijn_rekeningen_struct{ string nummer; //van de Rekeningen string naam; //van de Rekeningen string uitleg; //uitleg over de Rekeningen long account; //stand rekening }; typedef sequence<mijn_rekeningen_struct> mijn_rekeningen_useq;
2
//(toon_leden_struct) struct toon_leden_info_struct{ string voornaam; string familienaam; string straat; long nummer; long bus; long postnummer; string gemeente; string land; string geboortedatum; }; //(toon_leden_useq , structuur_groep_union) struct toon_leden_struct{ long nummer; //van de persoon string login; //van de persoon toon_leden_info_struct info; //van de persoon }; //medeRekeningEigenaars---toonLeden---toonPersonen typedef sequence toon_leden_useq;
//(toon_structuur_groep_struct) union toon_structuur_groep_union switch(short){ case 0:toon_leden_info_struct persoon; case 1:string uitleg; }; //toonStructuurGroep ---rekeningGebruikers struct toon_structuur_groep_struct{ long nummer; //van de persoon of groep string naam; //van de persoon of groep toon_structuur_groep_union info; //van de persoon }; typedef sequence toon_structuur_groep_useq; };
3
//******************************************************************************************** // UA //******************************************************************************************** module ua{ interface ua_client_if{ exception NotReady{string reason;}; void setClientRef(in long terminal_nummer, in client::client_ua_if client_ref)raises(NotReady); void clientShutDown(in long terminal_nummer)raises(NotReady); string getSessionFactoryRef(in string type,in long service_nummer)raises(NotReady); types::mijn_services_useq mijnServices(in long terminalnummer)raises(NotReady); types::mijn_groepen_useq mijnGroepen()raises(NotReady); types::mijn_terminals_useq mijnTerminals()raises(NotReady); types::mijn_rekeningen_useq mijnRekeningen()raises(NotReady); types::toon_leden_useq medeRekeningEigenaars(in string rekeningnummer)raises(NotReady); types::toon_structuur_groep_useq rekeningGebruikers(in string rekeningnummer) raises(NotReady); types::toon_leden_useq toonLeden(in long groepnummer)raises(NotReady); types::toon_structuur_groep_useq toonStructuurGroep(in long groepnummer)raises(NotReady); types::toon_leden_useq toonPersonen()raises(NotReady); types::mijn_rekeningen_struct toonRekening(in long groepnummer)raises(NotReady); types::provider_services_useq toonGroepServices(in long groep, in long terminal) raises(NotReady); types::provider_services_useq providerServices()raises(NotReady); types::gratis_provider_services_useq gratisProviderServices()raises(NotReady); types::help_struct getHelp(in long terminalnummer,in string caller)raises(NotReady);
void addGroepGroep(in long groepnummerhoofd, in long groepnummersub)raises(NotReady); void addPersoonGroep(in string persoonlogin, in long groepnummer)raises(NotReady); void addPersoonPrivilege(in string persoonlogin, in long privilegenummer, in long terminalnummer,in string rekeningnummer, in string rekeningnaam)raises(NotReady); void addGroepPrivilege(in long groepsnummer, in long privilegenummer, in long terminalnummer)raises(NotReady);
void addGroep(in string naam, in string uitleg, in string rekeningnummer)raises(NotReady);
void wisPersoonPrivilege(in string persoonlogin, in long privilegenummer, in long terminalnummer, in string rekeningnummer)raises(NotReady); void wisGroepPrivilege(in long groepnummer, in long privilegenummer, in long terminalnummer)raises(NotReady); void wisGroepUitGroep(in long hoofdgroep, in long subgroep)raises(NotReady); void wisPersoonUitGroep(in long hoofdgroep, in long persoon)raises(NotReady); void wisGroep(in long groep)raises(NotReady); };//interface
4
interface uaf_manager_if{ oneway void ref(in in in in // in
manager::monitor_if monitor_ref, subag::subagf_uaf_if subagf_ref, ucxt::ucxtf_uaf_if ucxt_ref, string sf_ref); //// sf::sf_ua_if service_factory_ref);
oneway void setDatabaseValues(in in in in
string string string string
driver, properties, user, password);
void monitor(in string obj, in boolean onoff); void shutdown(); };//interface uaf_manager_if
interface uaf_welcome_if{ ua_client_if getUserAgent(in long persoonnummer); };//interface uaf_welcome_if
interface uaf_if:uaf_manager_if, uaf_welcome_if; interface ua_if:ua_client_if; };//module ua
//******************************************************************************************* // ucxt //********************************************************************************************
module ucxt{ interface ucxt_ua_if{ exception NotReady{string reason;}; void add(in long terminalNummerArg,in client::client_ua_if client_ref)raises(NotReady); void wis(in long terminalNummerArg)raises(NotReady); void getConfig(in long terminalNummer, out long audio_khz,out long video)raises(NotReady); };//interface ucxt_ua_if
interface ucxtf_uaf_if{ ucxt_ua_if getUserContext(in long persoonnummer); };
interface ucxtf_manager_if{ oneway void ref(in manager::monitor_if
monitor_ref);
oneway void setDatabaseValues(in string driver, in string properties, in string user, in string password); void monitor(in string obj, in boolean onoff); void shutdown(); };//interface ucxt_manager_if
interface ucxtf_if: ucxtf_manager_if,ucxtf_uaf_if; interface ucxt_if: ucxt_ua_if; };//module ucxt
5
//******************************************************************************************* // subag //******************************************************************************************** module subag{ interface subag_ua_if{ exception NotReady{string reason;}; types::mijn_groepen_useq mijnGroepen()raises(NotReady); types::provider_services_useq providerServices()raises(NotReady); types::gratis_provider_services_useq gratisProviderServices()raises(NotReady); };//interface subag_ua_if
interface subagf_uaf_if{ subag_ua_if getSubscriptionAgent(in long persoonnummer); };//subagf_uaf_if
interface subagf_manager_if{ oneway void ref(in manager::monitor_if in subm::subm_subag_if in subrg::subrg_subag_if in sth::sth_subag_if
monitor_ref, subm_ref, subrg_ref, sth_ref);
oneway void setDatabaseValues(in string driver, in string properties, in string user, in string password); void monitor(in string obj, in boolean onoff); void shutdown(); };//interface subagf_manager_if
interface subagf_if: subagf_manager_if,subagf_uaf_if; interface subag_if: subag_ua_if; };//module subag
//******************************************************************************************** // subrg //******************************************************************************************** module subrg{ interface subrg_subag_if{ };//interface subrg_subag_if
interface subrg_manager_if{ oneway void ref(in manager::monitor_if
monitor_ref);
oneway void setDatabaseValues(in string driver, in string properties, in string user, in string password); void monitor(in string obj, in boolean onoff); void shutdown(); };//interface subrg_manager_if
interface subrg_if: subrg_manager_if,subrg_subag_if; };//module subrg
6
//****************************************************************************** // sth //****************************************************************************** module sth{ interface sth_subag_if{ exception NotReady{string reason;}; types::provider_services_useq providerServices()raises(NotReady); types::gratis_provider_services_useq gratisProviderServices()raises(NotReady); };//interface sth_subag_if
interface sth_manager_if{ oneway void ref(in manager::monitor_if
monitor_ref);
oneway void setDatabaseValues(in string driver, in string properties, in string user, in string password); void monitor(in string obj, in boolean onoff); void shutdown(); };//interface sth_manager_if
interface sth_if: sth_manager_if,sth_subag_if; };//module sth
//******************************************************************************************** // subm //******************************************************************************************** module subm{ interface subm_subag_if{ };//interface subm_subag_if
interface subm_manager_if{ oneway void ref(in manager::monitor_if
monitor_ref);
oneway void setDatabaseValues(in string driver, in string properties, in string user, in string password); void monitor(in string obj, in boolean onoff); void shutdown(); };//interface subm_manager_if
interface subm_if: subm_manager_if,subm_subag_if; };//module subm
7
//****************************************************************************** // client //****************************************************************************** module client{ interface client_ua_if{ };//interface
interface client_if: client_ua_if; };//module
//****************************************************************************** // manager //****************************************************************************** module manager{ interface monitor_if{ void monitor(in string in string in string in string in string };
bron_server, doel_server, if, time, text);
};
//******************************************************************************************** // sf //******************************************************************************************** //module sf{ // interface sf_ua_if{ // };//interface // // // interface sf_service_if{//dit moet ingevuld worden door de schrijvers van de sf // };//interface // // interface sf_if: sf_ua_if, sf_service_if; //};//module interface SessionFactory;
8
//******************************************************************************************** // welcome //********************************************************************************************
module welcome{ interface welcome_manager_if{ void ref(in manager::monitor_if monitor_if_ref, in ua::uaf_welcome_if uaf_welcome_if_ref); void setDatabaseValues(in string driver, in string properties, in string user, in string password); void monitor(in string obj, in boolean onoff); void shutdown(); };//interface
//worden voorlopig nog nergens gebruikt(voor tryAdres()) struct geboortedatum_type{ long jaar; short maand; short dag; }; struct person_type{ string voornaam; string familienaam; string straat; long nummer; long bus; long postnummer; string gemeente; string land; geboortedatum_type geboortedatum; }; interface welcome_client_if{ exception NotReady{string reason;}; boolean ring(in long terminal_nr, in string user_login, in string password, out boolean terminal_exist, out boolean user_exist, out boolean password_ok, out ua::ua_client_if useragent) raises(NotReady); void killConnection() raises(NotReady); boolean tryAdres(in person_type user) raises(NotReady); };//interface
interface welcome_if:welcome_client_if,welcome_manager_if; };//module welcome