Za´padoˇceska´ univerzita v Plzni Fakulta aplikovany´ch vˇed Katedra informatiky a vy´poˇcetn´ı techniky
Bakal´ aˇ rsk´ a pr´ ace Z´ asuvn´ e moduly a konfigurace dom´ en validaˇ cn´ıho serveru
Plzeˇ n 2012
Hung Duong Manh
Prohl´ aˇ sen´ı Prohlaˇsuji, ˇze jsem bakal´aˇrskou pr´aci vypracoval samostatnˇe a v´ yhradnˇe s pouˇzit´ım citovan´ ych pramen˚ u. V Plzni dne 6. kvˇetna 2012 Hung Duong Manh
Abstrakt Tato pr´ace popisuje, jak vytv´aˇret z´asuvn´e moduly a validaˇcn´ı dom´eny na validaˇcn´ı server pouˇz´ıvan´ ym Z´apadoˇceskou univerzitou v Plzni. V prvn´ı ˇca´sti je struˇcnˇe pops´an validaˇcn´ı server, jeho webov´e rozhran´ı, studentsk´e u ´lohy KIV/OOP a jak lze vytv´aˇret pravidla do PMD. Druh´a ˇc´ast se zab´ yv´a samotn´ ym vytv´aˇren´ım extern´ıch modul˚ u a posledn´ı ˇc´ast popisuje, jak jsou nakonfigurov´any validaˇcn´ı dom´eny KIV/OOP ve webov´em rozhran´ı.
Abstract This thesis describes how to create plugins and validation domains for the validation server used by University of West Bohemia. The first part briefly addresses the validation server, its web interface, student assignments for the course KIV/OOP and how to write a new PMD rule. The second part is a guide on how to create validation server plugins and the last part describes how KIV/OOP validation domains are configured in the web interface.
Podˇ ekov´ an´ı R´ad bych podˇekoval doc. Ing. Pavlu Heroutovi, Ph.D. za smˇerov´an´ı m´e ˇcinnosti a Ing. Luk´aˇsovi Valentovi a Bc. Veronice Dudov´e za ochotu mi s ˇc´ımkoliv pomoci a poradit.
Obsah ´ 1 Uvod
1
2 Teoretick´ yu ´ vod 2.1 Validaˇcn´ı server . . . . . . . . . . . . . . . . . . . . . . . . 2.1.1 Pˇr´ıstup na validaˇcn´ı server . . . . . . . . . . . . . . 2.1.2 Adres´aˇrov´a struktura validaˇcn´ıho serveru . . . . . . 2.1.3 Restartov´an´ı validaˇcn´ıho serveru . . . . . . . . . . . 2.2 Webov´e rozhran´ı validaˇcn´ı serveru . . . . . . . . . . . . . . 2.2.1 Adres´aˇrov´a struktura webov´eho rozhran´ı . . . . . . 2.2.2 Restartov´an´ı webov´eho rozhran´ı . . . . . . . . . . . 2.3 Testovac´ı kopie validaˇcn´ıho serveru s webov´ ym rozhran´ım . 2.4 KIV/OOP – Pˇredmˇet objektovˇe orientovan´e programov´an´ı 2.4.1 JUnit testy . . . . . . . . . . . . . . . . . . . . . . 2.4.2 Porovn´av´an´ı obr´azk˚ u . . . . . . . . . . . . . . . . . 2.4.3 Kontrola UML diagramu tˇr´ıd . . . . . . . . . . . . 2.5 PMD – statick´a anal´ yza k´odu . . . . . . . . . . . . . . . . 2.5.1 Vytvoˇren´ı pravidla Java tˇr´ıdou . . . . . . . . . . . 2.5.2 Vytvoˇren´ı pravidla pomoc´ı XPath . . . . . . . . . . 3 Z´ asuvn´ e moduly pro valid´ ator 3.1 Custom validace . . . . . . . . . . . . . . . . 3.1.1 Vytvoˇren´ı custom validace v Eclipse 3.1.2 Zprovoznˇen´ı custom validace . . . . . 3.2 Extern´ı vlastn´ı akce . . . . . . . . . . . . . . 3.2.1 Vytvoˇren´ı extern´ı vlastn´ı akce . . . . 3.2.2 Zprovoznˇen´ı extern´ı vlastn´ı akce . . . 3.3 Z´asuvn´e moduly pro KIV/OOP . . . . . . . 3.3.1 Porovn´an´ı dvou obr´azk˚ u . . . . . . . 3.3.2 Pouˇzit´ı custom validace . . . . . . . 3.4 Knihovna pro kontrolu UML diagram˚ u . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . . . . . . .
2 . 2 . 3 . 3 . 4 . 5 . 5 . 6 . 6 . 7 . 8 . 8 . 9 . 11 . 12 . 15
. . . . . . . . . .
17 17 18 20 23 23 26 28 28 30 31
. . . . . . . . . .
4 Validaˇ cn´ı dom´ eny pro 4.1 Kl´ıˇcov´e u ´lohy . . . ´ 4.2 Ulohy s kolekcemi . 4.3 JUnit u ´loha . . . .
KIV/OOP 35 . . . . . . . . . . . . . . . . . . . . . . . . 35 . . . . . . . . . . . . . . . . . . . . . . . . 38 . . . . . . . . . . . . . . . . . . . . . . . . 39
5 Z´ avˇ er
40
Literatura
42
Webov´ e zdroje
43
A Uk´ azka custom validace
44
B Uk´ azka extern´ı vlastn´ı akce
47
C CD Readme
52
´ 1 Uvod Na Katedˇre informatiky a v´ ypoˇcetn´ı techniky Fakulty aplikovan´ ych vˇed Z´apadoˇcesk´e univerzity byl vytvoˇren komplexn´ı syst´em umoˇzn ˇuj´ıc´ı automatizovan´e, ˇci poloautomatizovan´e vyhodnocov´an´ı studentsk´ ych samostatn´ ych prac´ı. ˇ kontroluje tzv. vaPrincipem je, ˇze pr´ace odevzdan´e pˇres Port´al ZCU lidaˇcn´ı server. Tento validaˇcn´ı server postupuje podle naprogramovan´ ych krok˚ u a pokud odevzdan´ y soubor neprojde validac´ı, nen´ı studentsk´a pr´ace pˇrijata. Doposud si validaˇcn´ı server vystaˇcil s jednoduchou metodou kontroly – porovn´an´ım v´ ystupu programu se vzorov´ ym textov´ ym souborem. Avˇsak s ohledem na moˇznosti validaˇcn´ıho serveru a moˇzn´ ym budouc´ım vyuˇzit´ım je tˇreba ˇreˇsit i dalˇs´ı metody kontroly. Takov´e kontroly mohou napˇr´ıklad zahrnovat spouˇstˇen´ı jednotkov´ ych test˚ u, porovn´av´an´ı grafick´eho v´ ystupu ˇci kontrolu UML diagram˚ u, pˇr´ıpadnˇe obecnˇe jakoukoliv programovatelnou uˇcitelskou kontrolu. Pro validaˇcn´ı server bylo tak´e novˇe vytvoˇreno webov´e uˇzivatelsk´e rozhran´ı, ˇ adn´ kter´e mˇelo za u ´kol zjednoduˇsit pr´aci s konfigurac´ı valid´atoru. Z´ y aktivn´ı pˇredmˇet vˇsak dosud nemˇel svoj´ı validaˇcn´ı dom´enu vytvoˇrenou v tomto webov´em rozhran´ı. C´ılem pr´ace je vytvoˇren´ı validaˇcn´ıch dom´en pro pˇredmˇet OOP ve webov´em rozhran´ı, coˇz bude br´ano jako pilotn´ı projekt pro budouc´ı vyuˇzit´ı konfigurace validaˇcn´ıho serveru v dalˇs´ıch pˇredmˇetech. Pr´ace d´ale pˇredpokl´ad´a vytvoˇren´ı nˇekolika nov´ ych z´asuvn´ ych modul˚ u pˇr´ımo pouˇziteln´ ych pro kontrolu v´ ystup˚ u studentsk´ ych prac´ı. K tomu je tˇreba vyuˇz´ıt vˇsech jiˇz existuj´ıc´ıch moˇznost´ı validaˇcn´ıho serveru.
1
2 Teoretick´y u´vod 2.1
Validaˇ cn´ı server
Jak´ ykoliv studijn´ı pˇredmˇet, ve kter´em je tˇreba odevzdat samostatnou pr´aci ˇ Tento zp˚ elektronicky, m˚ uˇze vyuˇz´ıt moˇznost odevzd´av´an´ı pˇres Port´al ZCU. usob odevzd´av´an´ı samostatn´ ych prac´ı m´a mnoho v´ yhod, n´as vˇsak hlavnˇe zaj´ım´a moˇznost kontrolovat odevzd´avan´e soubory pˇres validaˇcn´ı server. T´ım, ˇze se soubory kontroluj´ı validaˇcn´ım serverem, se zajist´ı t´emˇeˇr okamˇzit´a odpovˇed’ studentovi, zda jeho pr´ace vyhovuje poˇzadavk˚ um ˇci nikoliv. Student nemus´ı ˇcekat na v´ ysledky s t´ım, ˇze jeho pr´ace nen´ı spr´avnˇe a mus´ı jeˇstˇe nˇeco opravit. Vyuˇcuj´ıc´ı naopak nemus´ı podrobnˇe kontrolovat kaˇzdou pr´aci a to, zda pr´ace vyhovuje ˇci nikoliv, je stanoveno dle objektivn´ıho krit´eria, kter´e je pro vˇsechny pr´ace stejn´e. Validaˇcn´ı server funguje jako voliteln´a nadstavba odevzd´avac´ıho portletu, viz [11]. Portlet obdrˇz´ı odevzdan´ y soubor a ten pˇrepoˇsle validaˇcn´ımu serveru. Validaˇcn´ı server nejprve provede u ´vodn´ı dom´enov´e kontroly – napˇr. maxim´aln´ı moˇzn´a velikost souboru, povolen´e pˇr´ıpony atd. – a pokud soubor projde, spust´ı se samotn´ y validaˇcn´ı proces. Pro kaˇzd´ y validaˇcn´ı proces je vytvoˇren v´ ystup, do kter´eho m˚ uˇze autor validaˇcn´ıho procesu generovat informativn´ı, varovn´e ˇci chybov´e zpr´avy. Pokud dojde k pˇrid´an´ı chybov´e zpr´avy do v´ ystupu, neprojde soubor validac´ı jako takovou. Po dokonˇcen´ı validace je pak jej´ı v´ ystup pˇreveden do HTML str´anky a studentovi je na ni poskytnut odkaz. V´ ystup nemus´ı b´ yt ale pˇreveden jen do HTML str´anky pro studenta, dalˇs´ı formy v´ ystupu mohou b´ yt napˇr´ıklad uloˇzen´ı do datab´aze nebo XML souboru. HTML v´ ystupy se generuj´ı na adresu: http://vs.kiv.zcu.cz/validator/ Pˇresn´a cesta je urˇcena v souboru domain.xml a podle n´ı se vytvoˇr´ı adres´aˇrov´a struktura pro HTML v´ ystupy. Podrobnˇejˇs´ı informace o validaˇcn´ım serveru viz [2], [10].
2
Teoretick´y u ´vod
2.1.1
Validaˇcn´ı server
Pˇ r´ıstup na validaˇ cn´ı server
Adresa validaˇcn´ıho serveru je: validator.kiv.zcu.cz Pokud se na tuto adresu pˇripoj´ıme pomoc´ı protokolu HTTPS, dostaneme se na webov´e rozhran´ı validaˇcn´ıho serveru (viz 2.2). Pokud se na tuto adresu pˇripoj´ıme pomoc´ı protokolu SSH pˇres port 22, dostaneme se na samotn´ y souborov´ y syst´em validaˇcn´ıho serveru. SVN repozit´aˇr se zdrojov´ ymi k´ody se nach´az´ı na adrese: svn+ssh://forge.kiv.zcu.cz/home/svn/validator/ValidacniServer/trunk ´ Udaje pro pˇr´ıstup na validaˇcn´ı server a na SVN repozit´aˇr poskytuje a spravuje Ing. Luk´aˇs Valenta (
[email protected]).
2.1.2
Adres´ aˇ rov´ a struktura validaˇ cn´ıho serveru
/home/validator/validator | | VS.jar | restart | start | stop | [lib] | [data] | | [domains] | | | [common] | | | [ppa1] | | | | ... | | | | domain.xml | | | | run.policy | | | [ssp07] | | | ... | | [html] | | | vs.css | | [log] | | | vs.log | | [store] | | [workdir]
Uk´ azka 2.1: Adres´aˇrov´a struktura validaˇcn´ıho serveru 3
Teoretick´y u ´vod
Validaˇcn´ı server
Pro uˇcely vytv´aˇren´ı z´asuvn´ ych modul˚ u je tˇreba sezn´amit se s adres´aˇrovou strukturou a d˚ uleˇzit´ ymi soubory validaˇcn´ıho serveru. Uk´azka 2.1 je pˇrevzata z [10]. Protoˇze u ´ˇcty pro pˇr´ıstup na validaˇcn´ı server mohou m´ıt jinak nastaveny domovsk´e adres´aˇre po pˇrihl´aˇsen´ı, je v uk´azce 2.1 na prvn´ı ˇr´adce uvedena absolutn´ı cesta k ostr´emu validaˇcn´ımu serveru v r´amci souborov´eho syst´emu. N´ azev VS.jar
Pouˇ zit´ı hlavn´ı spustiteln´ y JAR serveru
restart
skript na restartov´an´ı valid´atoru
lib
sloˇzka pro pomocn´e knihovny
domain.xml
nastaven´ı validaˇcn´ı dom´eny
run.policy
nastaven´ı pr´av ve validaˇcn´ı dom´enˇe
workDir
doˇcasn´e pracovn´ı sloˇzky validac´ı, d˚ uleˇzit´e zejm´ena pro ladˇen´ı
Tabulka 2.1: Popis d˚ uleˇzit´ ych ˇca´st´ı validaˇcn´ıho serveru
2.1.3
Restartov´ an´ı validaˇ cn´ıho serveru
Obˇcas je po proveden´ı nˇejak´ ych zmˇen nutno validaˇcn´ı server restartovat, aby se zmˇeny projevily. Restart trv´a pˇribliˇznˇe dvˇe a p˚ ul sekundy, tud´ıˇz studenti by nemˇeli ani postˇrehnout, ˇze server nebˇeˇz´ı. Pˇresto je ale vhodnˇejˇs´ı prov´adˇet restart v dobˇe, kdy se neoˇcek´av´a, ˇze by studenti odevzd´avali sv´e pr´ace. M˚ uˇze se totiˇz st´at, ˇze zmˇeny, kter´e jsme provedli, budou vykon´avat jinou ˇcinnost, neˇz jakou jsme poˇzadovali, a server budeme muset restartovat v´ıcekr´at. Pˇri rozs´ahlejˇs´ıch zmˇen´ach je vhodn´e pouˇz´ıt nejdˇr´ıve testovac´ı server (viz 2.3) a na nˇem u ´pravy odladit. Restart validaˇcn´ıho serveru se prov´ad´ı tak, ˇze se pomoc´ı programu Putty pˇripoj´ıme na validaˇcn´ı server pˇres protokol SSH: validator.kiv.zcu.cz:22 a tam, v koˇrenov´e sloˇzce valid´atoru, spust´ıme skript restart (viz 2.1.2). ./restart
4
Teoretick´y u ´vod
2.2
Webov´e rozhran´ı validaˇcn´ı serveru
Webov´ e rozhran´ı validaˇ cn´ı serveru
V p˚ uvodn´ım validaˇcn´ım serveru bez webov´eho uˇzivatelsk´eho rozhran´ı byl cel´ y pr˚ ubˇeh validace ˇr´ızen skriptem process.xml, kter´ y obsahoval kombinaci XML element˚ u s JavaScriptov´ ym programem (Princip fungov´an´ı validaˇcn´ıho serveru – [10]). Pokud vyuˇcuj´ıc´ı nebyl detailnˇe sezn´amen s moˇznostmi konfigurace, bylo vytv´aˇren´ı validaˇcn´ıch dom´en obt´ıˇzn´e. Z tohoto d˚ uvodu vzniklo webov´e uˇzivatelsk´e rozhran´ı. Uˇzivatelsk´e rozhran´ı poskytuje srozumitelnˇejˇs´ı zp˚ usob, jak nastavit validaˇcn´ı dom´eny. Je vytvoˇreno pomoc´ı servlet˚ u a JSP str´anek a vyuˇz´ıv´a webov´ y sever Tomcat [2]. Samotn´ y validaˇcn´ı proces je rozdˇelen do posloupnosti krok˚ u, kter´e maj´ı jednoznaˇcnou funkci, a podm´ınku, za jak´e se spust´ı. Autor validace m˚ uˇze nav´ıc vytv´aˇret JavaScriptov´e promˇenn´e, kter´e jsou viditeln´e ze vˇsech krok˚ u. Pomoc´ı tˇechto promˇenn´ ych tak m˚ uˇze pˇred´avat data z jednoho krok˚ u do dalˇs´ıch.
Obr´ azek 2.1: Uk´azka krok˚ u validaˇcn´ı dom´eny
2.2.1
Adres´ aˇ rov´ a struktura webov´ eho rozhran´ı
/home/validator/tomcat/webapps/ROOT | | domenaNastaveni.jsp | domenaSmaz.jsp | ... | [css] | [imgs] | [js] | [META−INF] | [WEB−INF] | | [classes] | | [data] | | [libg
Uk´ azka 2.2: Adres´aˇrov´a struktura webov´eho rozhran´ı 5
Teoretick´y u ´vod
Testovac´ı kopie validaˇcn´ıho serveru s webov´ym rozhran´ım
N´ azev data
Pouˇ zit´ı jsou zde uloˇzeny jednotliv´e kroky n´ami vytvoˇren´ ych dom´en
lib
sloˇzka pro knihovny
Tabulka 2.2: Popis d˚ uleˇzit´ ych ˇca´st´ı webov´eho rozhran´ı Nˇekdy potˇrebujeme pˇrekop´ırovat urˇcit´e kroky z jedn´e dom´eny do druh´e nebo potˇrebujeme vytvoˇrit vˇetˇs´ı poˇcet krok˚ u najednou. V takov´em pˇr´ıpadˇe ˇ sen´ım je modifikovat n´aˇs by bylo klik´an´ı pˇres webov´e rozhran´ı pracn´e. Reˇ soubor s kroky ve sloˇzce WEB-INF/data. Tento soubor, kter´ y je pojmenovan´ y podle naˇseho Orion loginu, obsahuje vˇsechny dom´eny a jejich kroky, kter´e jsme v r´amci webov´eho rozhran´ı vytvoˇrili. Pro projeven´ı zmˇen v souboru staˇc´ı restartovat webov´e rozhran´ı, samotn´ y validaˇcn´ı server se restartovat nemus´ı.
2.2.2
Restartov´ an´ı webov´ eho rozhran´ı
Abychom restartovali webov´e rozhran´ı, mus´ıme restartovat webov´ y server Tomcat. To se provede podobn´ ym zp˚ usobem jako restartov´an´ı validaˇcn´ıho serveru (viz 2.1.3). Skripty na spuˇstˇen´ı a vypnut´ı Tomcatu jsou ale v: /home/validator/tomcat/bin
Samostatn´ y skript pro restart tu nen´ı, mus´ıme Tomcat vypnout a znovu zapnout skripty shutdown.sh a startup.sh. ./shutdown.sh ./startup.sh
2.3
Testovac´ı kopie validaˇ cn´ıho serveru s webov´ ym rozhran´ım
Pro u ´ˇcely testov´an´ı a ladˇen´ı validaˇcn´ıch dom´en a extern´ıch modul˚ u byl vytvoˇren testovac´ı validaˇcn´ı server, kter´ y je t´emˇeˇr identick´ y s ostr´ ym, pouze 6
Teoretick´y u ´vod KIV/OOP – Pˇredmˇet objektovˇe orientovan´e programov´an´ı
m´a jin´e cesty. Autoˇri validaˇcn´ıch dom´en zde mohou testovat sv´e konfigurace, aniˇz by pˇri tom naruˇsovali bˇeh ostr´eho serveru. Protoˇze se testovac´ı validaˇcn´ı server pouˇz´ıv´a pro v´ yvoj a ozkouˇsen´ı extern´ıch modul˚ u, poskytuje funkce, kter´e ostr´ y server dosud nevyuˇz´ıv´a. Do ostr´eho serveru se pak tyto moduly zavedou aˇz bude nutn´e. Adresa webov´eho rozhran´ı testovac´ıho valid´atoru je: https://validator.kiv.zcu.cz/val-test/ Pro pˇr´ıstup k souborov´emu syst´emu testovac´ıho valid´atoru je adresa stejn´a jako pro ostr´ y, viz 2.1.1. Samotn´ y testovac´ı valid´ator je pak um´ıstˇen ve sloˇzce: \home\valtest\val−test
2.4
KIV/OOP – Pˇ redmˇ et objektovˇ e orientovan´ e programov´ an´ı
Pˇredmˇet si klade za c´ıl nauˇcit studenty objektovˇe orientovan´ y styl programov´an´ı spolu s dobr´ ymi program´atorsk´ ymi n´avyky. Studenti pˇritom mimo jin´e pracuj´ı s JUnit testy, UML diagramy ˇci statickou kontrolou zdrojov´ ych k´od˚ u.[3] Samostatn´e projekty jsou vytvoˇreny tak, aby byly jednoduˇse strojovˇe ovˇeˇriteln´e. Tento pˇredmˇet je tedy velmi vhodn´ y pro kontrolu u ´loh pomoc´ı valid´atoru. Studenti v r´amci pˇredmˇetu pracuj´ı na celkem aˇz jeden´acti samostatn´ ych u ´loh´ach. Prvn´ıch osm u ´loh je kl´ıˇcov´ ych (tj. povinn´ ych) a t´ ykaj´ı se objektovˇe orientovan´eho designu, psan´ı JavaDoc dokumentace a vytv´aˇren´ı UML diagram˚ u. Dalˇs´ı dvˇe u ´lohy jsou na t´ema kolekce v Javˇe a posledn´ı u ´loha se zaob´ır´a vytv´aˇren´ım JUnit test˚ u. Jedn´ım z poˇzadavk˚ u t´eto pr´ace bylo vytvoˇrit validaˇcn´ı dom´eny pro pˇredmˇet KIV/OOP. Validaˇcn´ı dom´eny jako takov´e uˇz byly pˇredt´ım vytvoˇren´e, pouze bylo tˇreba je pˇrev´est do form´atu webov´eho rozhran´ı. Nˇekter´e dom´eny byly n´aslednˇe doplnˇen´e o dalˇs´ı kroky, aby byla kontrola pˇr´ısnˇejˇs´ı, jin´e bylo nutno kompletnˇe pˇredˇelat a vytvoˇrit k nim z´asuvn´e moduly, aby je bylo moˇzno spustit z webov´eho rozhran´ı. 7
Teoretick´y u ´vod KIV/OOP – Pˇredmˇet objektovˇe orientovan´e programov´an´ı
2.4.1
JUnit testy
Prvn´ıch osm u ´loh se kontroluje pomoc´ı JUnit test˚ u. JUnit je open source n´astroj na psan´ı a spouˇstˇen´ı jednotkov´ ych test˚ u pro programovac´ı jazyk Java [7]. Jednotkov´e testy funguj´ı tak, ˇze si program´ator nap´ıˇse urˇcitou sadu test˚ u, kter´e porovn´avaj´ı oˇcek´avanou a skuteˇcnou n´avratovou hodnotu metod, a pokud testy probˇehnou v poˇra´dku, lze pˇredpokl´adat, ˇze metody pracuj´ı spr´avnˇe. Jednou z v´ yhod jednotkov´ ych test˚ u je, ˇze po jejich vytvoˇren´ı m˚ uˇze prob´ıhat testov´an´ı zcela automaticky. S jednotkov´ ymi testy se tak´e poj´ı programovac´ı pˇr´ıstup, kdy nejdˇr´ıve se nap´ıˇsou jednotkov´e testy a aˇz potom se nap´ıˇse vlastn´ı k´od. Tomuto pˇr´ıstupu se ˇr´ık´a programov´an´ı ˇr´ızen´e testy“.[1] V samostatn´ ych u ´loh´ach pˇredmˇetu ” KIV/OOP si studenti zkouˇsej´ı oba zp˚ usoby pr´ace s jednotkov´ ymi testy, tedy jak situaci, kdy maj´ı k dispozici pouze jednotkov´e testy a musej´ı vytvoˇrit tˇr´ıdy a metody, tak situaci, kdy maj´ı ovˇeˇrit funkˇcnost tˇr´ıdy pomoc´ı test˚ u. Studenti kaˇzdou samostatnou kl´ıˇcovou u ´lohu odevzd´avaj´ı jako cel´ y projekt se zdrojov´ ymi soubory, v pracovn´ı sloˇzce na validaˇcn´ım serveru se pak vybran´e soubory projektu pˇrep´ıˇsou vzorov´ ymi a cel´ y projekt se zkompiluje. Po zkompilov´an´ı se spust´ı JUnit testy a pokud testy neohl´as´ı chybu, je projekt pˇrijat. Spoleˇcnˇe s testy se tak´e poˇr´ıd´ı sn´ımek obrazovky (studenti pracuj´ı s vykreslovac´ım pl´atnem).
2.4.2
Porovn´ av´ an´ı obr´ azk˚ u
Na rozd´ıl od zbyl´ ych sedmi kl´ıˇcov´ ych u ´loh odevzd´avaj´ı studenti v prvn´ı u ´loze pouze jeden soubor s testy a pˇr´ıpravkem (sada objekt˚ u, s nimiˇz budou testy pracovat). Studenti maj´ı na zaˇca´tku k dispozici pouze jednotkov´e testy a jejich u ´kolem je vykreslit na pl´atno pomoc´ı geometrick´ ych objekt˚ u jednoznaˇcnˇe definovan´ y obr´azek. Jak uˇz bylo ˇreˇceno, validace pro kl´ıˇcov´e projekty pˇredmˇetu KIV/OOP spol´eh´a v´ yhradnˇe na pr˚ ubˇeh JUnit test˚ u. Bylo by proto moˇzn´e, aby si studenti napsali sv˚ uj pˇr´ıpravek a testy si pozmˇenili, aby vyhovovaly jejich pˇr´ıpravku. To mˇelo za n´asledek, ˇze by testy na stranˇe serveru proˇsly, aˇckoliv by spr´avn´e nebyly. Vzhledem k tomu, ˇze studenti odevzd´avaj´ı pouze jeden soubor, nen´ı jednoduˇse moˇzn´e jej pˇrepsat vzorov´ ymi testy. Vyvstala tedy nutnost naj´ıt jin´ y zp˚ usob, jak ovˇeˇrit spr´avnost odevzdan´e pr´ace. 8
Teoretick´y u ´vod KIV/OOP – Pˇredmˇet objektovˇe orientovan´e programov´an´ı
Ze zm´ınˇen´eho d˚ uvodu se do procesu validace zaˇclenilo i poˇrizov´an´ı sn´ımku obrazovky, protoˇze obr´azek lze porovnat v˚ uˇci vzoru. Samotn´e porovn´av´an´ı dvou obr´azk˚ u ale v˚ ubec nen´ı trivi´aln´ı z´aleˇzitost. Pˇredpokl´adejme, ˇze bychom porovn´avali dva obr´azky ve form´atu JPEG. Vlivem komprese by obr´azky nemusely b´ yt bin´arnˇe totoˇzn´e, i kdyby byly vygenerov´any stejn´ ym programem a se stejn´ ym nastaven´ım. Naˇstˇest´ı lze poˇrizovat sn´ımek pl´atna do bezztr´atov´eho form´atu PNG. D´ale m´ame jistotu, ˇze vˇsechny poˇr´ızen´e sn´ımky budou m´ıt stejn´e rozliˇsen´ı, protoˇze studenti pracuj´ı se stejn´ ym frameworkem. Porovn´av´an´ı obr´azk˚ u se n´am tud´ıˇz zjednoduˇsilo na probl´em, kdy staˇc´ı pouze porovn´avat pixel po pixelu prvn´ı obr´azek s druh´ ym.
2.4.3
Kontrola UML diagramu tˇ r´ıd
Od p´at´e kl´ıˇcov´e u ´lohy pˇredmˇetu KIV/OOP aˇz do osm´e odevzd´avaj´ı studenti kromˇe samotn´ ych zdrojov´ ych k´od˚ u tak´e UML digramy tˇr´ıd.[5] Tyto UML diagramy tˇr´ıd vytv´aˇrej´ı v jednoduch´em programu zvan´em UMLet, kter´ y um´ı diagramy exportovat do form´atu PNG. Doposud se tyto diagramy tˇr´ıd musely kontrolovat ruˇcnˇe jako obr´azky. Pro zautomatizov´an´ı kontroly se zd´anlivˇe nab´ız´ı moˇznost kontrolovat diagramy stejnˇe jako v 2.4.2. Tento pˇr´ıstup je ale nepouˇziteln´ y, protoˇze aˇckoliv studenti pouˇzij´ı stejn´e tˇr´ıdy jako ve vzorov´em obr´azku, kaˇzd´ y obr´azek bude m´ıt jin´e rozloˇzen´ı. Naˇstˇest´ı vˇsak UMLet dovoluje ukl´adat diagramy jako XML soubory, tud´ıˇz lze snadno programovˇe z´ıskat strukturu diagramu. Uk´azka diagramu s dvˇema tˇr´ıdami a jednou relac´ı:
9
Teoretick´y u ´vod KIV/OOP – Pˇredmˇet objektovˇe orientovan´e programov´an´ı
10 <element> com.umlet.element.Class <x>20 20 <w>100 30 <panel attributes>Osoba <element> com.umlet.element.Class <x>250 20 <w>100 30 <panel attributes>Muz <element> com.umlet.element.Relation <x>90 0 <w>180 50 <panel attributes>lt=<<− 30;30;160;30
Uk´ azka 2.3: Diagram uloˇzen´ y v UMLet
Obr´ azek 2.2: V´ ysledek uk´azky 2.3 Za zm´ınku stoj´ı dvˇe skuteˇcnosti. Element type se uˇz nijak d´ale nedˇel´ı a to jak pro tˇr´ıdy, tak i pro relace. Kdyˇz chceme u tˇr´ıdy specifikovat, ˇze se jedn´a napˇr´ıklad o rozhran´ı, tak to lze prov´est pouze tak, ˇze se nap´ıˇse typ tˇr´ıdy jako text do obd´eln´ıku (element panel_attributes) a je jenom na autorovi diagramu, aby pouˇz´ıval konzistentn´ı znaˇcen´ı pro dan´ y typ tˇr´ıdy (v tomto pˇr´ıpadˇe <
>). 10
Teoretick´y u ´vod
PMD – statick´a anal´yza k´odu
Smˇer relace se urˇcuje pomoc´ı hodnot v elementu additional_attributes. Hodnoty jsou vˇzdy po dvojic´ıch a plat´ı, ˇze prvn´ı dvojice zprava se vztahuje na poˇca´teˇcn´ı bod relace a posledn´ı dvojice nalevo na koncov´ y bod relace. Dvojice jsou ve tvaru X, Y, kdy po pˇriˇcten´ı tˇechto hodnot k souˇradnic´ım X, Y relace z´ısk´ame v´ ysledn´e souˇradnice bodu. V naˇs´ı uk´azce je to (relace vede od Muz k Osoba): poˇca´teˇcn´ı bod:
◦ X = 90 + 160 = 250 ◦ Y = 0 + 30 = 30 koneˇcn´ y bod:
◦ X = 90 + 30 = 120 ◦ Y = 0 + 30 = 30 Pro zpracov´an´ı XML souboru s diagramem bylo moˇzn´e pouˇz´ıt technologii Simple API for XML (SAX) nebo Document Object Model (DOM). V podstatˇe bylo jedno jakou technologii zvol´ım, protoˇze na UMLet souborech by se neprojevila ˇza´dn´a z v´ yhod jednotliv´ ych technologi´ı. DOM vytvoˇr´ı strom uzl˚ u, kter´ y je po celou dobu v pamˇeti a ve kter´em lze pˇristupovat k jak´emukoliv uzlu. Jenˇze vzhledem k tomu, ˇze jednotliv´e prvky diagramu budu stejnˇe muset pˇrev´est na Java objekty, tak si t´ım nijak nepom˚ uˇzu. Nakonec jsem se rozhodl pro SAX, protoˇze i kdyˇz je zpracov´an´ı pouze sekvenˇcn´ı, tak je rychlejˇs´ı a m´enˇe n´aroˇcn´e na pamˇet’ neˇz u DOM [4], [9].
2.5
PMD – statick´ a anal´ yza k´ odu
PMD [8] je opensource n´astroj, kter´ y slouˇz´ı k anal´ yze zdrojov´ ych soubor˚ u napsan´ ych v jazyce Java. V pˇredmˇetech KIV/PPA1, KIV/PT ˇci KIV/JXT se pouˇz´ıv´a pˇredevˇs´ım pro v´ yuku spr´avn´ ych programovac´ıch praktik, ale je moˇzno ho pouˇz´ıt i pro jin´e u ´ˇcely, napˇr. odhalov´an´ı bug˚ u (pr´azdn´e try/catch pˇr´ıkazy) nebo hled´an´ı duplicitn´ıho k´odu. Chyby odhalen´e pomoc´ı PMD nejsou chyby v prav´em slova smyslu (tj. funkˇcnosti), ale sp´ıˇse chyby v kvalitˇe zdrojov´eho k´odu. Pouˇz´ıv´an´ı PMD je ve v´ yˇse uveden´ ych pˇredmˇetech voliteln´e. Pro pˇredmˇet KIV/OOP by se ale PMD mohlo st´at pˇrirozenou souˇca´st´ı validaˇcn´ıho 11
Teoretick´y u ´vod
PMD – statick´a anal´yza k´odu
procesu. V minulosti uˇz byly pokusy zaˇclenit PMD do validaˇcn´ıho serveru, bohuˇzel ale nebyly dotaˇzeny do zd´arn´eho konce. Nav´ıc v t´e dobˇe nebylo k dispozici ani webov´e rozhran´ı. Spouˇstˇen´ı PMD se prov´ad´ı pomoc´ı JAR souboru, kter´emu pˇred´ame jako parametry soubory, kter´e chceme zkontrolovat, typ v´ ystupu a pravidla, kter´a chceme pouˇz´ıt. Rozhodnˇe by tedy nebyl probl´em vytvoˇrit extern´ı modul do valid´atoru, kter´ y by spouˇstˇel PMD nad odevzdan´ ymi soubory, a v´ ysledek kontroly by pˇresmˇeroval do celkov´eho v´ ysledku validace. V pˇr´ıpadˇe, ˇze by se nepouˇzilo pˇr´ıliˇs mnoho sloˇzit´ ych pravidel, by PMD mohlo b´ yt pro studenty uˇziteˇcn´e. M´ıru sloˇzitosti stanov´ı snadno vyuˇcuj´ıc´ı. Nov´a pravidla do PMD lze vytv´aˇret jako Java tˇr´ıdy nebo jako XPath v´ yrazy.
2.5.1
Vytvoˇ ren´ı pravidla Java tˇ r´ıdou
PMD nezpracov´av´a samotn´e zdrojov´e soubory, pouze z nich parsuje Abstract Syntax Tree (AST) a s t´ımto stromem v´ yraz˚ u pak d´ale pracuje. public class Trida { int a; }
Uk´ azka 2.4: Jednoduch´a tˇr´ıda
TypeDeclaration ClassOrInterfaceDeclaration:Trida ClassOrInterfaceBody ClassOrInterfaceBodyDeclaration FieldDeclaration Type PrimitiveType:int VariableDeclarator VariableDeclaratorId:a
Uk´ azka 2.5: Odpov´ıdaj´ıc´ı AST Pravidla se p´ıˇs´ı tak, ˇze reagujeme na v´ yskyt, ˇci nev´ yskyt urˇcit´eho uzlu. Chceme-li vytvoˇrit nov´e pravidlo, mus´ıme jako prvn´ı vˇedˇet, na jak´ y uzel reagujeme. To zjist´ıme tak, ˇze pouˇzijeme program designer.bat, kter´ y je souˇc´ast´ı distribuce PMD. T´ımto programem zpracujeme zdrojov´ y k´od v Javˇe a dostaneme vygenerovan´ y AST. 12
Teoretick´y u ´vod
PMD – statick´a anal´yza k´odu
Dejme tomu, ˇze bychom chtˇeli vyvolat poruˇsen´ı pravidla pˇri jednoznakov´em pojmenov´an´ı instanˇcn´ı promˇenn´e typu int. Bude n´as tedy zaj´ımat uzel VariableDeclaratorId. Kdyˇz uˇz v´ıme, na jak´ y uzel budeme reagovat, tak si m˚ uˇzeme vytvoˇrit Java tˇr´ıdu: import net.sourceforge.pmd.*; import net.sourceforge.pmd.ast.*;
// Z knihovny ”pmd−(cisloVerze).jar”
public class OurRule extends AbstractJavaRule { public Object visit(ASTFieldDeclaration node, Object data) { Node type = node.jjtGetChild(0); Node varDeclarator = node.jjtGetChild(1); if (isInt(type)) { if (isOneCharLong(varDeclarator)) { addViolation(data, node); } } return super.visit(node,data); } private boolean isInt(Node type) { SimpleNode primitiveType = (SimpleNode)type.jjtGetChild(0); return (primitiveType instanceof ASTPrimitiveType && primitiveType.getImage().equals(”int”)); } private boolean isOneCharLong(Node varDeclarator) { SimpleNode varDeclaratorId = (SimpleNode)varDeclarator.jjtGetChild(0); return (varDeclaratorId instanceof ASTVariableDeclaratorId && varDeclaratorId.getImage().length() == 1); } }
Uk´ azka 2.6: Poruˇsen´ı pravidla pˇri jednoznakov´e instanˇcn´ı promˇenn´e typu int V metodˇe visit() mus´ıme jako prvn´ı argument uv´est pˇr´ımo nadˇrazen´ y uzel pro VariableDeclaratorId. Kdybychom chtˇeli, aby pravidlo platilo pro vˇsechny n´azvy promˇenn´ ych, tak bychom si vystaˇcili s VariableDeclarator. My ale chceme konkr´etnˇe pouze instanˇcn´ı promˇenn´e typu int, a proto mus´ıme vybrat FieldDeclaration (ASTFieldDeclaration). Metodou jjtGetChild() z´ısk´ame potomky uzlu FieldDeclaration, v naˇsem pˇr´ıpadˇe to jsou Type a VariableDeclarator. V konkr´etn´ıch podm´ınk´ach spojen´ ych s nˇejak´ ym uzlem bychom se vˇzdy mˇeli pˇresvˇedˇcit, ˇze se jedn´a o poˇzadovan´ y typ uzlu oper´atorem instanceof. 13
Teoretick´y u ´vod
PMD – statick´a anal´yza k´odu
Kdyby n´am totiˇz chybˇela tato podm´ınka v metodˇe isInt(), tak by n´am vznikla chyba pˇri promˇenn´e typu String. Uzel pro String nen´ı ASTPrimitiveType a tud´ıˇz nem´a ˇza´dn´ y parametr int. Jeˇstˇe je tˇreba vytvoˇrit tzv. ruleset neboli sadu pravidel, kter´ y vyuˇzije naˇsi vytvoˇrenou tˇr´ıdu. Vytvoˇr´ıme si libovolnˇe pojmenovan´ y XML soubor (napˇr´ıklad mycustomrules.xml), ve kter´em bude n´asleduj´ıc´ı: <description> Ukazka noveho pravidla <description> Instancni promenne typu int nesmi mit jeden znak! <example>
Uk´ azka 2.7: Ruleset V PMD pak pouˇzijeme tento ruleset napˇr´ıklad takto: java −cp 1;2;3;4 net.sourceforge.pmd.PMD analyzovanySoubor.java text mycustomrules.xml 1: cesta k souboru jaxen−(verze).jar // ve slozce lib 2: cesta k souboru asm−(verze).jar // stazeneho distribucniho 3: cesta k souboru pmd−(verze).jar // baliku 4: slozka s class souborem nasi Java tridy text: textovy vystup
14
Teoretick´y u ´vod
2.5.2
PMD – statick´a anal´yza k´odu
Vytvoˇ ren´ı pravidla pomoc´ı XPath
XPath je jazyk urˇcen´ y pro navigov´an´ı nad XML dokumenty a protoˇze PMD pracuje se strukturou zdrojov´eho k´odu jako se stromem, lze XPath pouˇz´ıt i zde. Kromˇe samotn´eho v´ ybˇeru uzl˚ u a atribut˚ u umoˇzn ˇuje XPath tak´e jednoduch´e v´ ypoˇcty (viz [6]). Vytvoˇren´ı nov´eho pravidla pomoc´ı XPath zaˇc´ın´a stejn´ ym zp˚ usobem jako u Java tˇr´ıdy – identifikujeme potˇrebn´ y uzel. Mˇejme tut´eˇz tˇr´ıdu jako v uk´azce 2.4 v sekci 2.5.1. N´astroj designer.bat um´ı kromˇe generov´an´ı AST tak´e vyhodnocovat XPath v´ yrazy nad dan´ ym AST. Napˇr´ıklad v´ yraz, kter´ y od koˇrene hled´a vˇsechny deklarovan´e promˇenn´e s n´azvem a“: ” //VariableDeclaratorId[@Image=”a”]
by n´am vypsal: ASTVariableDeclaratorId at line 2 column 5
Tentokr´at budeme cht´ıt vytvoˇrit pravidlo, aby n´azev jak´ekoliv promˇenn´e nebyl kratˇs´ı neˇz stanoven´e minimum (v uk´azce je minimum 3). Pravidlo se bude ps´at pˇr´ımo do rulesetu, napˇr´ıklad mycustomrules2.xml, do elementu value. <description> Detects when a field, formal or local variable is declared with a short name. <priority>3 <properties> <property name=”minimum” description=”The variable length reporting threshold” value=”3”/> <property name=”xpath” pluginname=”true”>
15
Teoretick´y u ´vod
PMD – statick´a anal´yza k´odu
<example>
Pouˇzit´ı rulesetu je podobn´e jako v 2.5.1, pouze nen´ı tˇreba pˇrid´avat do classpath sloˇzku s class souborem.
16
3 Z´asuvn´e moduly pro valid´ator S nasazen´ım webov´eho uˇzivatelsk´eho rozhran´ı je k dispozici mnohem intuitivnˇejˇs´ı zp˚ usob ovl´ad´an´ı. Cel´a validace z˚ ustala pod validaˇcn´ı dom´enou a pomoc´ı webov´eho rozhran´ı jsou nyn´ı jasnˇe patrn´e kroky, kter´e se maj´ı prov´est. Webov´e rozhran´ı toho ale samo o sobˇe moc neum´ı, pouze poskytuje pˇrehlednˇejˇs´ı prostˇred´ı. Funkˇcnost z´ısk´av´a aˇz pomoc´ı z´asuvn´ ych modul˚ u. Z´asuvn´e moduly se pouˇz´ıvaj´ı jako akce v jednotliv´ ych kroc´ıch. Lze je tedy oznaˇcovat jako vlastn´ı akce“. V textu budou d´ale oba tyto term´ıny za” mˇen ˇov´any. Tyto vlastn´ı akce by se mˇely programovat co moˇzn´a nejv´ıc modul´arnˇe. V dobˇe psan´ı tohoto textu je na ostr´em serveru k dispozici jen nˇekolik z´akladn´ıch vlastn´ıch akc´ı jako jsou Rozbalen´ı archivu, Najdi soubory ˇci Kontrola programu (akce zejm´ena urˇcen´e pro pˇredmˇet PPA1). Na testovac´ım validaˇcn´ım serveru jsou vˇsak k dispozici dalˇs´ı vlastn´ı akce, z nichˇz jedna je pro d´ale popisovan´e postupy podmiˇ nuj´ıc´ı. Jedn´a se o vlastn´ı akci Spuˇstˇen´ı custom validace. Oˇcek´av´a se, ˇze ostr´ y validaˇcn´ı server bude jeˇstˇe tento rok (2012) aktualizov´an na verzi, kde bude i tato vlastn´ı akce. Z´asuvn´e moduly pro validaˇcn´ı server lze vytvoˇrit dvˇema zp˚ usoby: jako custom validaci (n´azev vych´az´ı ze jm´ena hlavn´ıho rozhran´ı), nebo jako extern´ı vlastn´ı akci do webov´eho rozhran´ı. Vˇsechny d´ale uveden´e postupy jsou uvedeny pro operaˇcn´ı syst´em Windows 7 a pops´any podrobnˇeji, aby podle nich bylo moˇzn´e v budoucnu validace pˇripravovat.
3.1
Custom validace
Poˇ zadavky: Java SE SDK 6u30, Eclipse SDK (Indigo SR2), WinSCP, pˇr´ıstup k validaˇcn´ımu serveru.
17
Z´asuvn´e moduly pro valid´ator
Custom validace
Custom validace je starˇs´ı zp˚ usob vytv´aˇren´ı z´asuvn´ ych modul˚ u. V porovn´an´ı s druh´ ym zp˚ usobem nepodporuje JavaScriptov´e promˇenn´e webov´eho rozhran´ı a pokud potˇrebujeme mˇenit parametry akce, je to obt´ıˇznˇejˇs´ı (do domain.xml se dop´ıˇse vlastnost a ta se pak v k´odu z´ısk´av´a). V´ yhodou je vˇsak snadnˇejˇs´ı zprovoznˇen´ı novˇe vytvoˇren´e akce a ladˇen´ı. Z toho vˇseho vypl´ yv´a, ˇze custom validace se sp´ıˇse hod´ı pro specializovan´e a jednor´azov´e akce nebo pokud potˇrebujeme rychle nˇeco vyzkouˇset.
3.1.1
Vytvoˇ ren´ı custom validace v Eclipse
Pro vytvoˇren´ı custom validace je tˇreba m´ıt knihovnu VS-API.jar, kter´a je souˇc´ast´ı distribuce valid´atoru (k dispozici tak´e na pˇriloˇzen´em CD). 1. Vytvoˇ ren´ı nov´ eho projektu File → New → Java Project
Obr´ azek 3.1: Vytvoˇren´ı nov´eho projektu 2. Pojmenov´ an´ı projektu a nastaven´ı verze prostˇ red´ı V dalˇs´ım oknˇe zad´ame n´azev projektu a nastav´ıme verzi prostˇred´ı. Validaˇcn´ı server jeˇstˇe nepodporuje Javu 1.7, proto vybereme verzi 1.6. Nakonec klikneme na tlaˇc´ıtko Finish 3. Pˇ rid´ an´ı knihovny VS-API.jar do projektu Knihovnu VS-API.jar nakop´ırujeme do libovoln´e sloˇzky (napˇr. do sloˇzky projektu). V Eclipse v oknˇe Package Explorer klikneme na n´aˇs projekt prav´ ym tlaˇc´ıtkem a zvol´ıme Properties. Najdeme vlastnost Java Build Path a pot´e zvol´ıme z´aloˇzku Libraries. Zde klikneme na tlaˇc´ıtko Add External JARs... a zad´ame m´ısto, kam jsme nakop´ırovali knihovnu VS-API.jar. Po vybr´an´ı knihovny by se n´am mˇela zobrazit v seznamu knihoven. Nic dalˇs´ıho zde uˇz nepotˇrebujeme, proto d´ame OK. 18
Z´asuvn´e moduly pro valid´ator
Custom validace
Obr´ azek 3.2: Zad´an´ı n´azvu projektu a verze prostˇred´ı
Obr´ azek 3.3: Pˇrid´an´ı knihovny VS-API.jar do projektu 4. Vytvoˇ ren´ı tˇ r´ıdy s metodou validate() Vytvoˇr´ıme v Eclipse v naˇsem projektu novou tˇr´ıdu (nemus´ı m´ıt bal´ıˇcek). V t´eto tˇr´ıdˇe staˇc´ı uˇz jen implementovat rozhran´ı CustomValidation dostupn´e d´ıky knihovnˇe VS-API.jar, vytvoˇrit metodu validate() a m˚ uˇzeme zaˇc´ıt ps´at samotn´ y k´od validace. Celou hlaviˇcku metody validate() z´ısk´ame bud’ v Eclipse, kdy najedeme myˇs´ı na podtrˇzen´ y n´azev tˇr´ıdy a vybereme Add unimplemented methods, nebo z JavaDoc dokumentace valid´atoru.
19
Z´asuvn´e moduly pro valid´ator
Custom validace
Obr´ azek 3.4: Doplnˇen´ı metody validate() pomoc´ı funkce quick fix Vˇse, co se m´a bˇehem validace prov´est, se p´ıˇse do metody validate(). Metoda validate() m´a dva parametry a to ValidationInfo a FullValidationResult. ValidationInfo obsahuje data, kter´e n´am pˇred´a validaˇcn´ı server napˇr. serverem pˇrijat´ y soubor, atributy dom´eny, absolutn´ı cestu k doˇcasn´emu pracovn´ımu adres´aˇri apod. Do FullValidationResult se naopak generuj´ı informace, varov´an´ı a chyby, kter´e se n´aslednˇe vyp´ıˇs´ı do v´ ystupn´ı HTML str´anky. Dostupn´e metody tˇechto pˇredan´ ych objekt˚ u lze opˇet z´ıskat pomoc´ı doplˇ nov´an´ı k´odu v Eclipse nebo v JavaDoc dokumentaci valid´atoru.
public class ValidationOOP11 implements CustomValidation { @Override public void validate(ValidationInfo validationInfo, FullValidationResult fullValidationResult) { String filename = validationInfo.getInputFile().getName(); if (! filename.equals(”SpravnyNazev.java”)) { fullValidationResult.addError(”Odevzdavany soubor se nejmenuje ' SpravnyNazev.java'!”); } } }
Uk´ azka 3.1: Pˇr´ıklad custom validace
3.1.2
Zprovoznˇ en´ı custom validace
Po naprogramov´an´ı tˇr´ıdy s metodou validate() je tˇreba tuto tˇr´ıdu (a dalˇs´ı tˇr´ıdy, pokud byly vytvoˇreny) um´ıstit jako JAR soubor na validaˇcn´ı server a 20
Z´asuvn´e moduly pro valid´ator
Custom validace
pˇr´ısluˇsnˇe upravit validaˇcn´ı dom´enu. V pˇr´ıpadˇe, ˇze jeˇstˇe nem´ame validaˇcn´ı dom´enu, lze ji vytvoˇrit ve webov´em rozhran´ı. 1. Exportov´ an´ı projektu do JAR souboru V Eclipse v oknˇe Package Manager klikneme na n´aˇs projekt prav´ ym tlaˇc´ıtkem a vybereme Export. Ze skupiny Java zvol´ıme JAR file a klikneme na Next. Ve v´ ysledn´em JAR souboru jsou nutn´e pouze class soubory tˇr´ıd, proto m˚ uˇzeme soubory jako .classpath a .project odˇskrtnout. D˚ uleˇzit´e je, aby byla zaˇskrtnut´a moˇznost Export generated class files and resources. Tlaˇc´ıtkem Browse vybereme, kam chceme JAR soubor uloˇzit a klikneme na tlaˇc´ıtko Finish.
Obr´ azek 3.5: Volby pˇri exportov´an´ı do JAR souboru 2. Zkop´ırov´ an´ı vyexportovan´ eho souboru na validaˇ cn´ı server Pomoc´ı programu WinSCP se pˇripoj´ıme na validaˇcn´ı server. Ve sloˇzce data/domains (viz 2.1.2, strana 3) najdeme n´azev dom´eny, ve kter´e budeme cht´ıt vytvoˇrenou custom validaci pouˇz´ıt, a do t´eto dom´eny nakop´ırujeme vyexportovan´ y JAR soubor. ´ 3. Uprava souboru domain.xml Do souboru domain.xml ve sloˇzce dom´eny dopln´ıme n´azev zkop´ırova21
Z´asuvn´e moduly pro valid´ator
Custom validace
n´eho JAR souboru jako hodnotu z´aznamu domain.classpath. Z´aznam tedy bude vypadat pˇribliˇznˇe takto: <entry key=”domain.classpath”>Ukazka.jar
Pokud pouˇz´ıv´ame v´ıce knihoven, oddˇel´ıme je stˇredn´ıkem: <entry key=”domain.classpath”>Foo.jar; Bar.jar
´ 4. Uprava souboru run.policy Prov´ad´ıme-li bˇehem custom validace z´apis, mus´ıme nastavit pr´ava pro doˇcasnou pracovn´ı sloˇzku (v doˇcasn´e pracovn´ı sloˇzce bychom mˇeli prov´adˇet veˇsker´e operace spojen´e se soubory). Pod povolen´ı ˇc´ıst ze sloˇzky dom´eny si proto pˇrid´ame povolen´ı zapisovat v pracovn´ı sloˇzce: permission java.io.FilePermission ”\${validator.domaindir}/−”, ”read”; permission java.io.FilePermission ”\${validator.workdir}/−”, ”write”;
5. Vytvoˇ ren´ı kroku ve webov´ em rozhran´ı Pˇrihl´as´ıme se do webov´eho rozhran´ı na adrese: https://validator.kiv.zcu.cz a u vybran´e dom´eny klikneme na Uprav. Pot´e v sekci Kroky validace zvol´ıme nov´y krok. Zad´ame n´azev kroku a jako typ akce vybereme Vlastn´ı akce → Spuˇstˇen´ı custom validace. Do pole N´azev validace nap´ıˇseme cel´ y n´azev tˇr´ıdy (tj. n´azev i s bal´ıˇcky), na konci nesm´ı b´ yt ˇz´adn´a pˇr´ıpona. Upozorˇ nuji, ˇze n´azev tˇr´ıdy a n´azev JAR souboru jsou rozd´ıln´e vˇeci.
Obr´ azek 3.6: Krok s custom validac´ı
22
Z´asuvn´e moduly pro valid´ator
3.2
Extern´ı vlastn´ı akce
Extern´ı vlastn´ı akce
Poˇ zadavky: Java SE SDK 6u30, Eclipse SDK (Indigo SR2), WinSCP, Putty, pˇr´ıstup na validaˇcn´ı server, pˇr´ıstup na SVN se zdrojov´ ymi k´ody validaˇcn´ıho serveru nebo samotn´e zdrojov´e k´ody validaˇcn´ıho serveru
Extern´ı vlastn´ı akce podporuj´ı JavaScriptov´e promˇenn´e a umoˇzn ˇuj´ı napsat n´apovˇedu, kter´a se uˇzivateli zobraz´ı ve webov´em rozhran´ı. D´ale nab´ızej´ı snadnˇejˇs´ı zp˚ usob, jak mˇenit dynamick´e parametry validace. Vˇsechny vlastn´ı akce, kter´e jsou dostupn´e, se pak zobrazuj´ı ve webov´em rozhran´ı pˇri u ´pravˇe kroku pod volbou Vlastn´ı akce. Nev´ yhodou vlastn´ıch akc´ı je fakt, ˇze pˇri jejich zprovozˇ nov´an´ı je tˇreba rekompilovat validaˇcn´ı server (VS.jar) a n´aslednˇe pak novou verzi nahr´at na server. Z m´eho pohledu jsou extern´ı vlastn´ı akce sp´ıˇse vhodnˇejˇs´ı pro obecnˇejˇs´ı ˇcinnosti, kter´e budou potencion´alnˇe vyuˇz´ıv´any i jin´ ymi uˇzivateli.
3.2.1
Vytvoˇ ren´ı extern´ı vlastn´ı akce
Pro vytvoˇren´ı extern´ı vlastn´ı akce je tˇreba m´ıt knihovny externi.jar a js.jar (na pˇriloˇzen´em CD). Knihovna externi.jar obsahuje tˇr´ıdy z validaˇcn´ıho serveru potˇrebn´e pro naprogramov´an´ı validace a knihovna js.jar slouˇz´ı pro pr´aci se vstupn´ımi parametry Context a Scriptable [2]. 1. Vytvoˇ ren´ı nov´ eho projektu Viz krok ˇc´ıslo 1 v sekci 3.1.1 na stranˇe 18. 2. Pojmenov´ an´ı projektu a nastaven´ı verze prostˇ red´ı Viz krok ˇc´ıslo 2 v sekci 3.1.1 na stranˇe 18. 23
Z´asuvn´e moduly pro valid´ator
Extern´ı vlastn´ı akce
3. Pˇ rid´ an´ı knihoven externi.jar a js.jar do projektu Analogick´ y postup jako v kroku ˇc´ıslo 3 v sekci 3.1.1 na stranˇe 18. 4. Vytvoˇ ren´ı tˇ r´ıdy implementuj´ıc´ı rozhran´ı VlastniAkce public class Trida2 implements VlastniAkce {}
5. Implementace nutn´ ych metod Metody, kter´e je nutn´e implementovat, n´am vytvoˇr´ı s´am Eclipse po najet´ı kurzoru myˇsi na n´azev tˇr´ıdy a kliknut´ı volby Add unimplemented methods (podobnˇe jako na obr´azku 3.4 na str´ance 20). Jsou to metody: public String getHelp() public String getId() public String getKategorii() public String getNazev() public List<ParametrAkce> getParametry() public String getPopis() public void execute(ValidationInfo arg0, FullValidationResult arg1, Scriptable arg2, Context arg3, Collection<Parametr> arg4)
Metoda getHelp() vrac´ı ˇretˇezec s n´apovˇedou. Veˇsker´ y text n´apovˇedy mus´ı b´ yt v tomto jedin´em ˇretˇezci, pˇriˇcemˇz text mus´ı b´ yt naps´an pomoc´ı HTML znaˇcek. public String getHelp() { String help = ”Nadpis
”; help += ”Text napovedy
”; return help; }
Uk´ azka 3.2: Metoda getHelp() Metoda getId() vrac´ı identifik´ator, podle kter´eho se vlastn´ı akce odliˇs´ı od ostatn´ıch. Staˇc´ı zadat jm´eno tˇr´ıdy. public String getId() { return ”Trida2”; }
Uk´ azka 3.3: Metoda getId() Metoda getKategorii() vrac´ı kategorii, do kter´e vlastn´ı akce spad´a.
24
Z´asuvn´e moduly pro valid´ator
public String getId() { return KAT_SOUBOR; }
Extern´ı vlastn´ı akce
// Prace se soubory
Uk´ azka 3.4: Metoda getKategorii() Kromˇe v´ yˇse uveden´e kategorie existuje jeˇstˇe kategorie KAT_PROGRAM pro pr´aci s programy a KAT_DOC pro pr´aci s dokumenty. Metoda getNazev() vrac´ı n´azev, kter´ y se bude zobrazovat se seznamu vlastn´ıch akc´ı. public String getNazev() { return ”Trida 2 − ukazkova akce”; }
Uk´ azka 3.5: Metoda getNazev() Metoda getParametry() vrac´ı seznam parametr˚ u. Parametrem je myˇsleno napˇr´ıklad tlaˇc´ıtko na nahr´an´ı dat na server nebo r˚ uzn´e pˇrep´ınaˇce (viz obr. 3.7) V n´asleduj´ıc´ım pˇr´ıkladu je ˇreˇseno pˇrid´an´ı dvou parametr˚ u: n´azev souboru a ovl´adac´ı prvek pro nahr´an´ı dat na server. Pˇri vytvoˇren´ı objektu ParametrAkce se zad´avaj´ı ˇctyˇri argumenty – id, n´azev, popis a typ. Id se definuje jako tˇr´ıdn´ı konstanta. N´azev a popis jsou informace pro zobrazen´ı ve webov´em rozhran´ı a typ se ud´av´a jenom ve speci´aln´ıch pˇr´ıpadech.
Obr´ azek 3.7: Pˇr´ıklad parametr˚ u vlastn´ı akce
25
Z´asuvn´e moduly pro valid´ator
Extern´ı vlastn´ı akce
public class Trida2 implements VlastniAkce { public static final String PARAM_NAZEV_SOUBORU = ”Nazev souboru”; ... public List<ParametrAkce> getParametry() { ArrayList<ParametrAkce> list = new ArrayList<ParametrAkce>(); list.add(new ParametrAkce(PARAM_NAZEV_SOUBORU, ”Nazev souboru”, ”JavaScriptova promenna pro ulozeni nazvu souboru”, ””)); list.add(new ParametrAkce(”kontrola−programu/nahraj”, ”Nahrat testovaci data”, ”Nahrajte testovaci data vytvorena podle navodu”, ”anchor”)); return list; }
Uk´ azka 3.6: Metoda getParametry() Metoda getPopis() vrac´ı ˇretˇezec s popisem vlastn´ı akce. public String getPopis() { return ”Akce slouzi jako ukazka externi vlastni akce.”; }
Uk´ azka 3.7: Metoda getPopis() Metoda execute() vykon´av´a samotnou validaci. Z parametr˚ u metody jsou pro n´as nejd˚ uleˇzitˇejˇs´ı ValidationInfo (informace o validaci), FullValidationResult (v´ ysledek validace) a Scriptable (JavaScriptov´e promˇenn´e). Pˇr´ıklad n´ıˇze vyp´ıˇse do v´ ysledku validace absolutn´ı cestu k odevzdan´emu souboru. public void execute(ValidationInfo info, FullValidationResult result, Scriptable scope, Context jsContext, Collection<Parametr> param) { String path = info.getInputFile().getAbsolutePath(); result.addInfo(path); }
Uk´ azka 3.8: Metoda execute()
3.2.2
Zprovoznˇ en´ı extern´ı vlastn´ı akce
Zprovoznˇen´ı bude tentokr´at vyˇzadovat znovusestaven´ı a restart valid´atoru. 1. Exportov´ an´ı projektu do JAR souboru Viz krok ˇc´ıslo 1 v sekci 3.1.2 na stranˇe 21 26
Z´asuvn´e moduly pro valid´ator
Extern´ı vlastn´ı akce
´ 2. Uprava souboru MANIFEST.MF Ve sloˇzce, kam jsme vygenerovali JAR soubor, si vytvoˇr´ıme textov´ y soubor (napˇr. manifest.txt). Tento textov´ y soubor bude obsahovat pouze jednu ˇr´adku: AKCE: nazevVlastniAkce
kde n´azev mus´ı b´ yt jedineˇcn´ y pˇres vˇsechny akce. M˚ uˇze se napˇr´ıklad pouˇz´ıt n´azev tˇr´ıdy implementuj´ıc´ı rozhran´ı VlastniAkce. V t´e sam´e sloˇzce si otevˇreme pˇr´ıkazovou ˇr´adku a zad´ame: jar umf manifest.txt nazevJARSouboru.jar
Tento pˇr´ıkaz zajist´ı, ˇze se do MANIFEST.MF dopln´ı ˇr´adka ze souboru manifest.txt. Alternativnˇe lze t´eˇz pouˇz´ıt archivovac´ı program, otevˇr´ıt n´aˇs JAR soubor a MANIFEST.FM upravit ruˇcnˇe. 3. Zkop´ırov´ an´ı vyexportovan´ eho souboru na validaˇ cn´ı server Postupujeme jako v kroku ˇc´ıslo 2 v sekci 3.1.2 na stranˇe 21. Tentokr´at vˇsak budeme kop´ırovat do jin´ ych sloˇzek. JAR soubor mus´ıme zkop´ırovat do sloˇzkek: lib tomcat/webapps/ROOT/WEB-INF/lib
Pˇriˇcemˇz tyto cesty plat´ı pro ostr´ y validaˇcn´ı server. ´ 4. Uprava souboru build.properties Soubor build.properties se nach´az´ı v SVN repozit´aˇri se zdrojov´ ymi k´ody validaˇcn´ıho serveru. Tento soubor je tˇreba upravit tak, aby ˇra´dky libraries a libraries.spaced obsahovaly cestu k JAR souboru, kter´ y jsme zkop´ırovali do sloˇzky lib. libraries libraries.spaced
= lib/commons−vfs−1.1.jar;...;lib/Ukazka2.jar = lib/commons−vfs−1.1.jar ... lib/Ukazka2.jar
5. Spuˇ stˇ en´ı build.xml (ant) Provedeme sestaven´ı pomoc´ı souboru build.xml, kter´ y se nach´az´ı v SVN repozit´aˇri. Do sloˇzky out/JARs by se n´am mˇel vygenerovat soubor VS.jar.
27
Z´asuvn´e moduly pro valid´ator
Z´asuvn´e moduly pro KIV/OOP
6. Nahr´ an´ı nov´ e verze VS.jar na server Pˇres WinSCP nahrajeme VS.jar do koˇrenov´eho adres´aˇre validaˇcn´ıho serveru a pˇrep´ıˇseme starou verzi. 7. Restartov´ an´ı validaˇ cn´ıho serveru Viz sekce 2.1.3 na stranˇe 4. 8. Restartov´ an´ı webov´ eho rozhran´ı Viz sekce 2.2.2 na stranˇe 6.
3.3 3.3.1
Z´ asuvn´ e moduly pro KIV/OOP Porovn´ an´ı dvou obr´ azk˚ u
Pro vytvoˇren´ı tohoto modulu staˇcila jedin´a tˇr´ıda. Modul navazuje na vlastn´ı akci Kontrola programu OOP, kter´a pro kaˇzd´ y soubor (z odevzd´avan´eho JAR souboru), jehoˇz n´azev konˇc´ı slovem Test, spouˇst´ı JUnit testy a generuje pˇri tom sn´ımek obrazovky. Tento sn´ımek pojmenovan´ y screenshot.png ukl´ad´a do pracovn´ı sloˇzky validace. Metoda validate() naˇcte vygenerovan´ y obr´azek screenshot.png a vzorov´ y obr´azek vzor.png, kter´ y mus´ıme nahr´at spoleˇcnˇe s testovac´ımi daty. Oba tyto obr´azky jsou pak pˇrevedeny na pole pixel˚ u. public class PorovnatPNG implements VlastniAkce { public void execute(ValidationInfo info, FullValidationResult result, Scriptable scope, Context jsContext, Collection<Parametr> parametry) { ... // Kontrola existence potrebnych souboru String sampleImage = info.getDomain().getDomainProperties().getProperty( ”image.sample name”); // Vlastnost, ktera se musi dopsat do domain.xml // rika, jak se ma jmenovat vzorovy soubor File validationImage = new File(workDir, sampleImage); ... // Nacteni obrazku sample = ImageIO.read(validationImage); ... // Prevedeni obrazku na pixely PixelGrabber grab1 = new PixelGrabber(sample, 0, 0, −1, −1, false); ... // Vytvoreni pole s pixely
28
Z´asuvn´e moduly pro valid´ator
Z´asuvn´e moduly pro KIV/OOP
int [] data1 = null; ... int width = grab1.getWidth(); int height = grab1.getHeight(); data1 = new int[width * height]; data1 = (int[])grab1.getPixels();
Pixely jsou uloˇzen´e jako int hodnota ve tvaru 0xAARRGGBB, kde AA je alpha sloˇzka barvy a zbytek jsou RGB sloˇzky. Pokud jsou pole totoˇzn´a, nemus´ı se nic ˇreˇsit a pˇrid´ame pouze informativn´ı zpr´avu, ˇze je v´ ystup v poˇra´dku. Pro porovn´av´an´ı jsem pouˇzil metodu Arrays.equals(), kter´a vrac´ı true, pokud jsou obˇe pole stejnˇe velk´a a kaˇzd´ y prvek prvn´ıho pole je stejn´ y jako odpov´ıdaj´ıc´ı prvek druh´eho pole. V pˇr´ıpadˇe, ˇze pole stejn´a nejsou, mus´ı se cyklem proj´ıt vˇsechny prvky. Aby bylo moˇzn´e studentovi uk´azat, kde pˇresnˇe se jeho obr´azek liˇs´ı od vzorov´eho, je nutn´e vytvoˇrit jak´ ysi rozd´ılov´ y obr´azek. Rozd´ılov´ y obr´azek se vytvoˇr´ı zesvˇetlen´ım pixel˚ u, kter´e jsou stejn´e v obou pol´ıch, a pixelem s ˇcervenou barvou v m´ıstˇe, kde se vytvoˇren´ y obr´azek liˇs´ı od vzorov´eho. if (data1[i + j*width] == data2[i + j*width]) { pixel = data1[i + j*width]; diffData[i + j*width] = brighten(pixel); } else { diffData[i + j*width] = markDifference(); }
Zesvˇetlen´ı RGB hodnoty se uk´azalo b´ yt m´ırnˇe obt´ıˇznˇejˇs´ı, protoˇze RGB model se zesvˇetlov´an´ım nebo ztmavov´an´ım bez zmˇeny barevn´eho odst´ınu nepoˇc´ıt´a. Z RGB modelu proto mus´ıme vytvoˇrit HSB (Hue, Saturation, Brightness) model a zmˇenit poˇzadovan´e sloˇzky. float [] hsbVals = Color.RGBtoHSB(red, green, blue, null); // Zmena saturace a svetlosti Color brighter = Color.getHSBColor(hsbVals[0], 0.2f * hsbVals[1], 0.5f
*
(1f + hsbVals[2]));
Po vygenerov´an´ı rozd´ılov´eho obr´azku jej uloˇz´ıme a pˇrekop´ırujeme z pracovn´ı sloˇzky na server s v´ ysledky validac´ı (vs.kiv.zcu.cz/validator). Pˇri kop´ırov´an´ı mus´ıme db´at na to, aby sn´ımek obrazovky i rozd´ılov´ y obr´azek mˇely unik´atn´ı n´azev, protoˇze vˇsechny obr´azky se ukl´adaj´ı do jedn´e sloˇzky pro celou validaˇcn´ı dom´enu. K tomu pouˇzijeme metodu System.currentTimeMillis().
29
Z´asuvn´e moduly pro valid´ator
Z´asuvn´e moduly pro KIV/OOP
String destinationPath = info.getDomain().getDomainProperties().getProperty( ”image.destination path”); // Musi se dopsat do domain.xml String diffImage = String.valueOf(”Diff ” +System.currentTimeMillis()) + ”.png”; ImageIO.write(bufferedImage, ”png”, new File(destinationPath + File.separator + diffImage));
Nakonec jeˇstˇe vloˇz´ıme odkaz na obr´azek do v´ ystupu validace. result.addInfo(”Rozdily oproti spravnemu obrazku .”);
Cel´ y zdrojov´ y k´od je v pˇr´ıloze B.
3.3.2
Pouˇ zit´ı custom validace
V jedn´e z u ´loh studenti maj´ı za u ´kol pˇripravit sadu testovac´ıch pˇr´ıpad˚ u, kter´e odhal´ı probl´emy v jim poskytnut´e knihovnˇe, konkr´etnˇe v souboru Osoba.java. Odevzd´av´a se jedin´ y soubor OsobaTest.java. D´ale n´asledujou okomentovan´e ˇc´asti zdrojov´eho k´odu custom validace. Cel´ y zdrojov´ y k´od je pˇr´ıloze A. public class ValidationOOP11 implements CustomValidation { final String JUNIT_JAR = ”/home/valtest/val−test/lib/junit−4.8.2.jar”; // final String JUNIT JAR = ”/home/validator/validator/lib/junit−4.8.2.jar”;
Cesta k JUnit knihovnˇe je d´ana napevno v k´odu, protoˇze jsem nepˇriˇsel na to, jak zjistit tuto cestu nez´avisle na struktuˇre serveru. Pˇri pouˇzit´ı na ostr´em serveru bude proto tˇreba pˇrehodit cesty. Abychom mohli testy spustit, mus´ıme nejdˇr´ıve OsobaTest.java zkompilovat, abychom z´ıskali OsobaTest.class. Pokud se podaˇr´ı soubor zkompilovat, pˇresuneme jej do podsloˇzky testy. Tato podsloˇzka je nutn´a z d˚ uvodu pouˇzit´ı bal´ıˇcku. Do classpath pak pˇrid´ame celou pracovn´ı sloˇzku. JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); compilationResult = compiler.run(null, null, errorOutput, ”−classpath”, JUNIT_JAR +”:” + osobaPath, ”−encoding”, ”UTF−8”, inputFile.getAbsolutePath()); ... File classFile = new File(testyDir.getAbsolutePath() + File.separator + ”OsobaTest.class”); File oldClassFile = new File(inputFile.getAbsolutePath().replace(”java”, ”class”)); oldClassFile.renameTo(classFile);
30
Z´asuvn´e moduly pro valid´ator
Knihovna pro kontrolu UML diagram˚ u
Spust´ı se JUnit testy z OsobaTest a vˇsechny by mˇely odhalit konkr´etn´ı chyby. Chyby (respektive jejich popis) mus´ı b´ yt identick´e se vzorov´ ymi, kter´e studenti maj´ı v zad´an´ı. for (Failure fail: result.getFailures()) { String chyba = fail.getDescription().getMethodName() + ”: ” + fail.getMessage(); if (mnozinaHlaseni.remove(chyba) == true) { fullValidationResult.addInfo(”Nalezeno: ” +chyba); }
Aby byl tedy odevzdan´ y soubor OsobaTest.java povaˇzov´an za spr´avn´ y, mus´ı b´ yt nalezeny vˇsechny chyby.
3.4
Knihovna pro kontrolu UML diagram˚ u
Tuto knihovnu jsem vytvoˇril pro pouˇzit´ı v custom validaci. Cel´a knihovna se ˇ ri tˇr´ıdy jsou v bal´ıˇcku data, kter´ skl´ad´a z celkem dev´ıti tˇr´ıd. Ctyˇ y zajiˇst’uje vytvoˇren´ı objekt˚ u z XML souboru, a zbyl´ ych pˇet tˇr´ıd je v bal´ıˇcku logic, kter´ y pracuje s vytvoˇren´ ymi objekty v pamˇeti. [data] Handler IUMLReader UMLElement UMLReaderSax [logic] UMLClass UMLDiagram UMLRelation UMLRelationType UMLUtils
Tˇr´ıda UMLReaderSax implementuje rozhran´ı IUMLReader a slouˇz´ı k naˇcten´ı vˇsech prvk˚ u UMLet souboru (pˇr´ıpona uxf) do pamˇeti. Jak uˇz z n´azvu vypl´ yv´a, je pouˇzita technologie SAX (viz 2.4.3). UMLReaderSax vyuˇz´ıv´a pro samotn´e parsov´an´ı tˇr´ıdu Handler, kter´a pˇresnˇe ˇr´ık´a, jak´ ym zp˚ usobem se maj´ı z´ıskat hodnoty z XML souboru. Pro kaˇzd´ y zpracovan´ y prvek element se vytvoˇr´ı nov´ y objekt v Javˇe typu UMLElement, coˇz je v podstatˇe reprezentace prvku element v pamˇeti. Seznam vˇsech UMLElement objekt˚ u se pak pˇred´av´a d´al metodou getAllElements(). 31
Z´asuvn´e moduly pro valid´ator
Knihovna pro kontrolu UML diagram˚ u
Nejpodstatnˇejˇs´ı tˇr´ıdou je tˇr´ıda UMLDiagram, kter´a z objekt˚ u UMLElement vytv´aˇr´ı objekty diagramu a poskytuje nad nimi dotazy. Pˇri vytv´aˇren´ı objekt˚ u UMLClass a UMLRelation se mus´ı z UMLElement nˇejak´ ym zp˚ usobem z´ıskat, o jak´ y typ tˇr´ıdy nebo relace se jedn´a. Pot´ıˇz je v tom, ˇze klasifikace je pouze textov´a a vytv´aˇr´ı ji autor diagramu. Zjiˇst’ov´an´ı typu tˇr´ıdy (tˇr´ıda, rozhran´ı, abstraktn´ı tˇr´ıda atd., pˇr´ıpadnˇe n´avrhov´e vzory) je tedy napevno podle v´ yskytu nˇejak´eho znaku nebo ˇr´adky. Z uk´azkov´eho UML diagramu, kter´ y jsem mˇel k dispozici, jsem vypozoroval ˇctyˇri moˇznosti, jak m˚ uˇze b´ yt tˇr´ıda pops´ana. pouze n´ azev tˇr´ıdy, n´ azev tˇr´ıdy, barva obd´eln´ıku, typ tˇr´ıdy uvnitˇr znak˚ u <<“ a >>“, n´azev tˇr´ıdy, ” ” typ tˇr´ıdy uvnitˇr znak˚ u <<“ a >>“, n´azev tˇr´ıdy, barva obd´eln´ıku. ” ” <panel_attributes><<singleton>> Seznamka bg=red
Uk´ azka 3.9: Tˇr´ıda typu singleton; n´azvem Seznamka a ˇcervenou barvou Samotn´a klasifikace prob´ıh´a tak, ˇze kontroluji, zda se v popisu vyskytuje ˇretˇezec >>“ nebo znak pro novou ˇr´adku. Tato metoda je silnˇe z´avisl´a na ” tom, ˇze studenti budou m´ıt jasnˇe stanoven´e stejn´e znaˇcen´ı a budou se ho drˇzet. D´ale je nutn´e si uvˇedomit, ˇze i typ tˇr´ıdy nen´ı omezen a m˚ uˇze b´ yt jak´ ykoliv. Relace jsou na tom podobnˇe. Tvar ˇsipek se autoˇri UMLet rozhodli ukl´adat jako prvn´ı ˇr´adku v popisu elementu. Viz uk´azka 2.2 na stranˇe 10. Pro urˇcen´ı typu relace mus´ı b´ yt typ spojen´ y s tvarem ˇsipky. Komplikace ale opˇet nast´avaj´ı, pokud se autor diagramu rozhodne d´at popis relace nad/pod ˇsipku a na tvar ˇsipky nebude db´at. Tyto situace neˇreˇs´ım, protoˇze by to bylo zbyteˇcnˇe komplikovan´e. Klasifikace relac´ı je tedy pouze na z´akladˇe tvaru ˇsipky (viz tabulka 3.1). Zda je relace mezi konkr´etn´ımi dvˇema tˇr´ıdami, se stanov´ı prohled´an´ım vˇsech tˇr´ıd a kontrolou, zda poˇca´teˇcn´ı a koncov´ y bod relace leˇz´ı uvnitˇr obd´eln´ıku nˇekter´e z tˇr´ıd. Vˇsechny objekty typu UMLRelation proto maj´ı atributy 32
Z´asuvn´e moduly pro valid´ator
Knihovna pro kontrolu UML diagram˚ u
Znaˇ cen´ı <- nebo -
Typ asociace
<.
z´avislost
<<-
dˇedˇen´ı
<<.
implementace rozhran´ı
<<<-
agregace
<<<<-
kompozice
Podoba
Tabulka 3.1: Druhy relac´ı v UMLet from a to typu UMLClass. Pokud je nˇejak´a relace obousmˇern´a, pak se mus´ı vytvoˇrit dvˇe relace, kter´e budou m´ıt prohozen´e from a to. V moment´aln´ı podobˇe se dotazy vykon´avaj´ı nad dvˇema seznamy – seznam s UMLClass a UMLRelation. Seznamy nejsou nijak logicky propojen´e, protoˇze mˇe nenapadl pˇr´ıpad, kde by to bylo potˇrebn´e. Vzhledem k tomu, ˇze modul jeˇstˇe nebyl vyzkouˇsen pro vytvoˇren´ı validace a nen´ı k dispozici ˇza´dn´a zpˇetn´a vazba, lze oˇcek´avat, ˇze modul se bude v budoucnu jeˇstˇe upravovat. K dispozici jsou nyn´ı tyto dotazy: public public public public public public
boolean noteExists() boolean classExists(String name) boolean interfaceExists(String name) int checkNumberOfRelationsOf(String name) boolean checkRelationFromTo(String from, String to) boolean checkRelationTypeFromTo(UMLRelationType type, String from, String to)
Pouˇzit´ı je pak takov´e, ˇze v tˇr´ıdˇe pro custom validaci se vytvoˇr´ı objekt UMLDiagram, kter´emu se jako parametr pˇred´a cesta k odevzd´avan´emu diagramu a objekt typu FullValidationResult. Aby autor validace nemusel st´ale ps´at podm´ınky pro porovn´av´an´ı oˇcek´avan´e a navr´acen´e hodnoty, vytvoˇril jsem v tˇr´ıdˇe UMLUtils statickou metodu assertEquals(), kter´a porovn´av´a pˇredan´e 33
Z´asuvn´e moduly pro valid´ator
Knihovna pro kontrolu UML diagram˚ u
hodnoty a v pˇr´ıpadˇe nerovnosti pˇrid´a do v´ ysledku validace chybu s textem errorMessage: public static void assertEquals(String errorMessage, boolean expected, boolean returned)
Pro pˇr´ıklad 2.3 ze strany 10 mohou testy vypadat takto: import java.io.File; import logic.UMLDiagram; import logic.UMLRelationType; import logic.UMLUtils; import cz.zcu.validationserver.CustomValidation; import cz.zcu.validationserver.validation.FullValidationResult; import cz.zcu.validationserver.validation.ValidationInfo;
public class Test implements CustomValidation { @Override public void validate(ValidationInfo validationInfo, FullValidationResult fullValidationResult) { File inputFile = validationInfo.getInputFile(); UMLDiagram diagram = new UMLDiagram(inputFile.getAbsolutePath(), fullValidationResult); UMLUtils.assertEquals(”Trida 'Osoba' neexistuje.”, true, diagram.classExists(”Osoba”)); UMLUtils.assertEquals(”Trida 'Muz' neexistuje.”, true, diagram.classExists(”Muz”)); UMLUtils.assertEquals(”Mezi tridou 'Muz' a 'Osoba' neni dedicnost”, true, diagram.checkRelationTypeFromTo(UMLRelationType.INHERITANCE, ”Muz”, ”Osoba”)); } }
Uk´ azka 3.10: Pouˇzit´ı assertEquals()
34
4 Validaˇcn´ı dom´eny pro KIV/OOP Vˇsechny vytvoˇren´e dom´eny byly u ´spˇeˇsnˇe otestov´any na odevzdan´ ych u ´loh´ach z let 2011/2012 a 2010/2011.
4.1
Kl´ıˇ cov´ eu ´ lohy
Validaˇcn´ı dom´eny pro kl´ıˇcov´e u ´lohy maj´ı t´emˇeˇr stejn´ y obsah. Na zaˇca´tku je vˇzdy akce Rozbal ZIP. U t´eto akce mus´ı b´ yt jeˇstˇe vyplnˇen´ y parametr C´ılov´y adres´aˇr, kter´ y bude pouˇzit v dalˇs´ı f´azi pˇri kontrole existence konkr´etn´ıch soubor˚ u (obr. 4.2).
Obr´ azek 4.1: Kroky pro validaˇcn´ı dom´enu u ´lohy 04
Obr´ azek 4.2: Detail kroku rozbaleni N´asleduje kontrola existence povinn´ ych soubor˚ u a sloˇzek. Kaˇzd´a kl´ıˇcov´a u ´loha m´a jin´e povinn´e soubory a typicky soubor˚ u s ˇc´ıslem u ´lohy pˇrib´ yv´a. Nevytv´aˇrel jsem kontrolu existence pro u ´plnˇe vˇsechny soubory, pouze ty nejd˚ uleˇzitˇejˇs´ı, protoˇze mi pˇriˇslo nepˇrehledn´e m´ıt ve validaˇcn´ı dom´enˇe des´ıtky 35
Validaˇcn´ı dom´eny pro KIV/OOP
Kl´ıˇcov´e u ´lohy
krok˚ u (jsou to soubory, kter´e maj´ı studenti jednoznaˇcnˇe uveden´e v zad´an´ı). Pro vyhled´av´an´ı soubor˚ u je pouˇzita akce Najdi soubory (obr. 4.3), u kter´e je tˇreba uv´est v jak´e sloˇzce se m´a hledat (v´ yˇse zmiˇ novan´ y C´ılov´y adres´aˇr ), co se m´a hledat (regul´arn´ı v´ yraz) a JavaScriptovou promˇennou, do kter´e bude uloˇzen poˇcet nalezen´ ych soubor˚ u/sloˇzek. Pokud akce ˇza´dn´ y vyhovuj´ıc´ı soubor nenajde, bude tato JavaScriptov´a promˇenn´a rovna nule.
Obr´ azek 4.3: Detail kroku hledej_rozmer Dalˇs´ı krok je vloˇzen´ı chyby do v´ ysledku validace, pokud nebude soubor ˇci sloˇzka nalezena (obr. 4.4). Tyto dva kroky, hled´an´ı souboru a pˇr´ıpadn´e vloˇzen´ı chyby pˇri nenalezen´ı, se opakuj´ı pro vˇsechny povinn´e soubory/sloˇzky.
Obr´ azek 4.4: Detail kroku nenalezeno_rozmer 36
Validaˇcn´ı dom´eny pro KIV/OOP
Kl´ıˇcov´e u ´lohy
Na konci f´aze hled´an´ı povinn´ ych soubor˚ u/sloˇzek je pak krok, kter´ y ukonˇc´ı validaci, v pˇr´ıpadˇe, ˇze se ve v´ ysledku validace jiˇz vyskytuje chyba (obr. 4.5).
Obr´ azek 4.5: Detail kroku konec_chyba Posledn´ım krokem je akce Kontrola programu OOP. Zde je nutn´e vysvˇetlit, jak se nahr´avaj´ı testovac´ı data. Testovac´ı data m˚ uˇzeme nahr´at bud’ pˇres webov´e rozhran´ı tlaˇc´ıtkem Nahr´at testovac´ı data nebo pˇres WinSCP. Pˇres webov´e rozhran´ı se testovac´ı data vˇzdy nahr´avaj´ı jako zip archiv (koncovka mus´ı b´ yt mal´ ymi p´ısmeny). Archiv se rozbal´ı do sloˇzky validation_data v dan´e dom´enˇe na serveru a pokud nebude archiv obsahovat sloˇzky, rozbal´ı se do validation_data rovnou. Akce Kontrola programu OOP byla p˚ uvodnˇe vytvoˇrena tak, ˇze se poˇc´ıtalo s jednou validaˇcn´ı dom´enou pro vˇsechny u ´lohy a nahr´an´ım vˇsech testovac´ıch dat najednou, neboli ˇze sloˇzka validation_data obsahovala podsloˇzky pojmenovan´e ˇc´ıslem u ´lohy. Kdyˇz tedy chceme m´ıt pro kaˇzdou u ´lohu vlastn´ı validaˇcn´ı dom´enu, mus´ıme m´ıt ve sloˇzce validation_data podsloˇzku s ˇc´ıslem u ´lohy a aˇz v n´ı testovac´ı data pro danou dom´enu. Pˇri nahr´an´ı archivu, kter´ y obsahuje zabalenou sloˇzku, bychom ale zjistili, ˇze se do validation_data rozbalily pouze soubory a sloˇzka se nevytvoˇrila. Je proto zapotˇreb´ı zabalit do archivu sloˇzku dvakr´at vnoˇrenˇe. 01.zip [01] [01] Barva.java Elipsa.java ...
Pouˇzijeme-li WinSCP, tento probl´em nemus´ıme ˇresit. Pˇripoj´ıme se na validaˇcn´ı server, vytvoˇr´ıme sloˇzku validation_data, v n´ı vytvoˇr´ıme sloˇzku s ˇc´ıslem u ´lohy a pˇrekop´ırujeme do n´ı testovac´ı data.
37
´ Ulohy s kolekcemi
Validaˇcn´ı dom´eny pro KIV/OOP
U prvn´ı u ´lohy je nav´ıc krok s porovn´av´an´ım vygenerovan´eho sn´ımku obrazovky se vzorov´ ym sn´ımkem. Akce nem´a ˇz´adn´e parametry, ale je tˇreba poˇc´ıtat s t´ım, ˇze vzorov´ y obr´azek mus´ı b´ yt ve sloˇzce validation_data a do domain.xml se mus´ı dopsat n´azev vzorov´eho obr´azku: <entry key=”image.sample name”>vzor.png
Prvn´ı u ´loha m´a jeˇstˇe jednu zvl´aˇstnost. I kdyˇz se neodevzd´av´a archiv ale soubor OsobaTest.java, pˇresto je prvn´ım krokem rozbalen´ı. Je to z d˚ uvodu, aby bylo moˇzno pouˇz´ıt akci Najdi soubory, kter´a vyˇzaduje uv´est adres´aˇr, ve kter´em se m´a hledat. To m´a za n´asledek, ˇze se pˇri odevzd´av´an´ı vyp´ıˇse, ˇze se nejedn´a o archiv a cel´a validace skonˇc´ı. Aby validace pokraˇcovala, mus´ı se pouˇz´ıt trik. Do souboru nl/text.properties ve sloˇzce dom´eny se dop´ıˇse vlastnost file.is_not_archive a jej´ı hodnota se ponech´a pr´azdn´a. file.is_not_archive =
Kl´ıˇcov´e u ´lohy pouˇz´ıvaj´ı sv˚ uj run.policy, ve kter´em jsou pr´ava pro knihovny a pro vytv´aˇren´ı sn´ımk˚ u (jsou k dispozici na pˇriloˇzen´em CD). V implicitn´ım domain.xml, kter´ y se vytvoˇr´ı s novou dom´enou, se vˇetˇsinou akor´at mus´ı zmˇenit poloˇzky html_output_dir, html_output_url a accept_extensions, popˇr´ıpadˇe jeˇstˇe domain.classpath. Poloˇzky html_output_dir a html_output_url urˇcuj´ı, kam se budou generovat v´ ystupn´ı HTML soubory. <entry key=”html output url”>/var/www/validator/val−test/oop01 <entry key=”html output dir”>/var/www/validator/val−test/oop01
Pokud bychom se chtˇeli pˇres webov´ y prohl´ıˇzeˇc kouknout do sloˇzky, kam se generuj´ı HTML soubory, staˇc´ı nahradit /var/www/ za vs.kiv.zcu.cz/.
4.2
´ Ulohy s kolekcemi
´ Ulohy s kolekcemi maji podobn´e kroky jako kl´ıˇcov´e u ´lohy, pouze m´ısto posledn´ı akce Kontrola programu OOP maj´ı Kontrola programu s parametry (obr. 4.6). Studenti odevzd´avaj´ı JAR soubor, kter´ y jde spustit a kter´ y potˇre38
Validaˇcn´ı dom´eny pro KIV/OOP
JUnit u ´loha
buje zadat argumenty. Do pole Argumenty t´eto akce se zapisuj´ı argumenty, kter´e bychom beˇznˇe zad´avali do pˇr´ıkazov´e ˇradky pˇri spuˇstˇen´ı. Pouze pˇred argument, kter´ y oznaˇcuje v´ ystupn´ı soubor, se mus´ı napsat -o, aby se tento v´ ystupn´ı soubor dal vytvoˇrit.
Obr´ azek 4.6: Vlastn´ı akce Kontrola programu s parametry Testovac´ı data pro tuto akci mus´ı m´ıt ve validation_data dvˇe sloˇzky: input_data a vysledky. Do input_data se d´avaj´ı soubory, kter´e budeme potˇrebovat jako vstup, a do vysledky se d´a vzorov´ y textov´ y soubor, v˚ uˇci kter´emu budeme porovn´avat v´ ystup studentovy u ´lohy. Porovn´an´ı se provede metodou compareFiles() tˇr´ıdy StreamComparator. Dojde-li k nˇejak´e chybˇe pˇri spouˇstˇen´ı programu, m˚ uˇze se st´at, ˇze ve v´ ysledku validace bude chyba, ale nebudou uvedeny ˇza´dn´e dalˇs´ı podrobnosti. V t´eto situaci je vhodn´e pod´ıvat se do doˇcasn´eho pracovn´ıho adres´aˇre, kam vlastn´ı akce Kontrola programu s parametry vygenerov´av´a chybov´ y textov´ y soubor.
4.3
JUnit u ´ loha
Jeden´act´a u ´loha m´a pouze jeden krok. V tomto kroku se pouˇzije akce Spuˇstˇen´ı custom validace pro spuˇstˇen´ı ValidationOOP11. Viz sekce 3.3.2 na stranˇe 30.
39
5 Z´avˇer Cel´a pr´ace mˇela dva hlavn´ı c´ıle. Prvn´ım z nich bylo vyuˇzit´ı jiˇz existuj´ıc´ıho webov´eho rozhran´ı pro uˇzivatelsky pˇr´ıjemnou konfiguraci validaˇcn´ıch dom´en (jeden pˇredmˇet typicky obsahuje nˇekolik validaˇcn´ıch dom´en). Popisovan´ yu ´kol byl proveden na 11 dom´en´ach pro pˇredmˇet KIV/OOP. Toto lze povaˇzovat za u ´spˇeˇsn´ y pilotn´ı projekt re´aln´eho nasazen´ı webov´eho konfigur´atoru. Cel´ y postup konfigurace dom´en byl d˚ uslednˇe pops´an, takˇze se podle nˇej budou moci v budoucnu pˇr´ısluˇsn´ı vyuˇcuj´ıc´ı jin´ ych pˇredmˇet˚ u ˇr´ıdit. Protoˇze existuje konfigurace 11 dom´en, lze tento u ´kol povaˇzovat za splnˇen´ y. Druh´ y hlavn´ı u ´kol pˇredstavoval vytvoˇren´ı tˇr´ı kompletnˇe nov´ ych z´asuvn´ ych modul˚ u. Tyto moduly umoˇzn ˇuj´ı principi´alnˇe zcela odliˇsn´e zp˚ usoby validace studentsk´ ych u ´loh. Dˇr´ıve bylo moˇzn´e porovn´avat jen textov´ y v´ ystup, v souˇcasn´e dobˇe mnou vytvoˇren´e moduly umoˇzn ˇuj´ı porovn´avat grafick´ y v´ ystup a t´eˇz kontrolu UML diagram˚ u. Nav´ıc byl splnˇen poˇzadavek na ovˇeˇren´ı moˇznosti libovoln´e program´atorsk´e kontroly, coˇz bylo tˇret´ım zm´ınˇen´ ym modulem splnˇeno. Vˇsechny tˇri z´asuvn´e moduly jsou zcela funkˇcn´ı a jejich zdrojov´ y k´od odpov´ıd´a souˇcasn´ ym poˇzadavk˚ um (dokumentace apod.). Vˇsechny tˇri zm´ınˇen´e moduly jsou jiˇz souˇca´st´ı konfigurace v´ yˇse uveden´ ych validaˇcn´ıch dom´en. V dokumentu je tak´e nav´ıc pops´ano, jak rozˇs´ıˇrit pravidla pro statickou kontrolu zdrojov´eho k´odu pomoc´ı PMD. Kontrola pomoc´ı PMD se tak bude moci st´at volitelnou souˇc´ast´ı validaˇcn´ıho procesu. Vˇsechny body zad´an´ı byly splnˇeny a validaˇcn´ı dom´eny jsou pˇripraveny k nasazen´ı. Celou pr´aci na t´eto problematice vˇsak nepovaˇzuji za dokonˇcenou. Hodl´am zde v dalˇs´ım obdob´ı d´ale spolupracovat a to v r´amci prob´ıhaj´ıc´ıho rozvojov´eho projektu, na jehoˇz ˇreˇsen´ı se pod´ıl´ım. Lze totiˇz pˇredpokl´adat, ˇze v budoucnu – pˇri nasazen´ı v ostr´em provozu – vzniknou poˇzadavky na dalˇs´ı rozˇsiˇrov´an´ı funkˇcnosti jak z´asuvn´ ych modul˚ u, tak i samotn´ ych validaˇcn´ıch dom´en.
40
Seznam zkratek AST
Abstract Syntax Tree - stromov´a reprezentace syntaktick´e struktury zdrojov´eho k´odu
DOM
Document Object Model - multiplatformn´ı a jazykovˇe nez´avisl´e rozhran´ı pro navigaci v XML dokumentech
HTML
Hypertext Markup Language - znaˇckovac´ı jazyk webov´ ych str´anek
HTTP
Hypertext Transfer Protocol - internetov´ y protokol
JPEG
Joint Photographic Experts Group - form´at pro ukl´ad´an´ı bitmapov´ ych obr´azk˚ u ztr´atovou kompres´ı
PNG
Portable Network Graphics - form´at pro bitmapov´ ych obr´azku bezztr´atovou kompres´ı
SAX
Simple API for XML - jednoduch´e rozhran´ı pro parsov´an´ı XML dokument˚ u
SSH
Secure Shell - bezpeˇcn´ y s´ıt’ov´ y protokol
SVN
Apache Subversion - syst´em pro spr´avu a verzov´an´ı zdrojov´ ych k´od˚ u
UML
Unified Modeling Languange - standardizovan´ y jazyk pro modelov´an´ı programov´ ych syst´em˚ u
XML
Extensible Markup Language - znaˇckovac´ı jazyk
41
ukl´ad´an´ı
Literatura [1] BECK, K.: Test Driven Development: By Example. Addison-Wesley Professional, 2003, ISBN 0321146530. ´ V.: Webov´a konfigurace validaˇcn´ıho serveru. Bakal´aˇrsk´a pr´ace, [2] DUDOVA, Z´apadoˇcesk´a univerzita v Plzni, Fakulta aplikovan´ ych vˇed, 2010. [3] HYNAR, M.: Java n´astroje. Neocortex s.r.o., 2004, ISBN 08-86330-16-8. [4] MCLAUGHLIN, B.: Java & XML. O’Reilly, 2001, ISBN 0-596-00197-5. [5] SCHMULLER, J.: Mysl´ıme v jazyku UML. Grada publishing, 2001, ISBN 80-247-0029-8.
42
Webov´ e zdroje [6] XML Path Language (XPath) 2.0 (Second Edition) [Online]. Posledn´ı aktualizace v lednu 2011 [cit. 6. kvˇetna 2012], dostupn´e z: http://www.w3.org/TR/xpath20/. [7] CLARK, M.: JUnit FAQ [Online]. Posledn´ı aktualizace v u ´noru 2006 [cit. 6. kvˇetna 2012], dostupn´e z: http://junit.sourceforge.net/doc/faq/faq.htm. [8] JENSEN, J.: PMD - Welcome to PMD [Online]. Posledn´ı aktualizace v lednu 2012 [cit. 6. kvˇetna 2012], dostupn´e z: http://pmd.sourceforge.net/. [9] MEGGINSON, D.: Megginson Technologies: Simple API for XML [Online]. ©2012 [cit. 6. kvˇetna 2012], dostupn´e z: http://www.megginson.com/downloads/SAX/. [10] VALENTA, L.: Validaˇcn´ı server [Online]. Publikov´ano v z´aˇr´ı 2007 [cit. 6. kvˇetna 2012], dostupn´e z: http://vs.kiv.zcu.cz/doc/index.html. [11] VALENTA, L.: Podpora v´yuky - Uˇzivatelsk´a pˇr´ıruˇcka [Online]. Posledn´ı aktualizace v ˇcervnu 2008 [cit. 6. kvˇetna 2012], dostupn´e z: http://portal.zcu.cz/zdroje/podporavyuky/help/.
43
A Uk´azka custom validace import import import import import import import import import import
java.io.File; java.io.FileNotFoundException; java.io.FileOutputStream; java.io.OutputStream; java.net.MalformedURLException; java.net.URL; java.net.URLClassLoader; java.util.Arrays; java.util.HashSet; java.util.Set;
import javax.tools.JavaCompiler; import javax.tools.ToolProvider; import org.junit.runner.Result; import org.junit.runner.notification.Failure; import import import import
cz.zcu.validationserver.CustomValidation; cz.zcu.validationserver.ValidationResult; cz.zcu.validationserver.validation.FullValidationResult; cz.zcu.validationserver.validation.ValidationInfo;
/** * Trida pro kontrolu 11.ulohy z OOP pomoci CustomValidation. *
@author Duong Manh Hung, [email protected] / public class ValidationOOP11 implements CustomValidation { * *
// NUTNO ZMENIT na ostrem validatoru !!! final String JUNIT_JAR = ”/home/validator/validator/lib/junit−4.8.2.jar”; // final String JUNIT JAR = ”/home/valtest/val−test/lib/junit−4.8.2.jar”; static String[] hlaseni = { ”testSetJmeno: Chybne jmeno: expected: but was:”, ”testSetVyskaDolniRozsah: Chybna vyska: expected:<50> but was:<51>”, ”testSetVyskaHorniRozsah: Chybna vyska: expected:<250> but was:<251>”, ”testSetVahaVyjimka: Unexpected exception, expected<java.lang.IllegalArgumentException> but was<java.lang.IllegalAccessError>”, ”testSetVahaDolu: Chybna vaha: expected:<91.0> but was:<92.0>” }; @Override public void validate(ValidationInfo validationInfo, FullValidationResult fullValidationResult) { String osobaPath = validationInfo.getDomain().getDomainDir().getAbsolutePath() + File. separator + ”Osoba.jar”; File errorFile = new java.io.File(validationInfo.getWorkDir(), ”error.txt”); File inputFile = validationInfo.getInputFile(); OutputStream errorOutput = null; try { errorOutput = new FileOutputStream(errorFile); } catch (FileNotFoundException e1) { // TODO Auto−generated catch block
44
Uk´azka custom validace
e1.printStackTrace(); } if (! ”OsobaTest.java”.equals(inputFile.getName())) { // vlozeni chyby do vysledku fullValidationResult.addError(”Soubor se nejmenuje OsobaTest.java!”, ValidationResult.VR_INVALID_INPUT); return; } if (inputFile.length() == 0) { // vlozim varovani do vysledku fullValidationResult.addWarning(”Odevzdany soubor je prazdny!”); return; } JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); // Zkompilovani poslaneho souboru // od 4.argumentu metody run jsou argumenty pro zkompilovani int compilationResult = −1; if (errorOutput != null) { compilationResult = compiler.run( null, null, errorOutput, ”−classpath”, JUNIT_JAR +”:” +osobaPath, ”−encoding”, ”UTF−8”, inputFile.getAbsolutePath()); } else { compilationResult = compiler.run( null, null, null, ”−classpath”, JUNIT_JAR +”:” +osobaPath, ”−encoding”, ”UTF−8”, inputFile.getAbsolutePath()); } if (compilationResult != 0) { fullValidationResult.addError(”Chyba pri kompilaci souboru OsobaTest.java”); } // Vsechny cinnosti se souborem jsou na serveru provadeny v tmp slozce ve workDir String workDirPath = inputFile.getAbsolutePath().replace(inputFile.getName(), ””); File testyDir = new File(workDirPath + ”testy”); testyDir.mkdir(); // Presunuti zkompilovaneho .class souboru do adresare testy ( kvuli classpath testy .OsobaTest) File classFile = new File(testyDir.getAbsolutePath() + File.separator + ”OsobaTest.class”); File oldClassFile = new File(inputFile.getAbsolutePath().replace(”java”, ”class”)); oldClassFile.renameTo(classFile); // Nahrani .class souboru do classpath File workDir = new File(workDirPath); File osobaJar = new File(osobaPath); URL url1 = null; URL url2 = null; try { url1 = workDir.toURI().toURL(); url2 = osobaJar.toURI().toURL(); } catch (MalformedURLException e) { // TODO Auto−generated catch block e.printStackTrace(); return; } URL [] urls = new URL[]{url1, url2}; ClassLoader cl = new URLClassLoader(urls);
45
Uk´azka custom validace
Class cls = null; try { cls = cl.loadClass(”testy.OsobaTest”); } catch (ClassNotFoundException e) { fullValidationResult.addError(”Trida nebyla nalezena”); e.printStackTrace(); return; } Set<String> mnozinaHlaseni = new HashSet<String>(Arrays.asList(hlaseni)); // Spusteni tridy pod JUnit Result result = org.junit.runner.JUnitCore.runClasses(cls); fullValidationResult.addInfo(”Probehlo celkem: ” +result.getRunCount() +” testu.”); for (Failure fail: result.getFailures()) { String chyba = fail.getDescription().getMethodName() + ”: ” + fail.getMessage(); String tmp = chyba.replace(”<”, ”<”); tmp = tmp.replace(”>”, ”>”); if (mnozinaHlaseni.remove(chyba) == true) { fullValidationResult.addInfo(”Nalezeno: ” +tmp); } } int pocet = hlaseni.length − mnozinaHlaseni.size(); if (pocet < hlaseni.length) { fullValidationResult.addError(”Odhaleno pouze ” + pocet + ” chyb z ” + hlaseni.length +”. Zbyvaji chyby:”); System.out.println(); for (String hlaseni : mnozinaHlaseni) { // Nahrazeni <> entitami pro zobrazeni v HTML String resultMessage = hlaseni.replace(”<”, ”<”); resultMessage = resultMessage.replace(”>”, ”>”); fullValidationResult.addError(resultMessage); } } else { fullValidationResult.addInfo(”Odhaleny vsechny chyby.”); return; } } }
46
B Uk´azka extern´ı vlastn´ı akce import import import import import import import import import import import import import
java.awt.Color; java.awt.Graphics2D; java.awt.Image; java.awt.Toolkit; java.awt.image.BufferedImage; java.awt.image.MemoryImageSource; java.awt.image.PixelGrabber; java.io.File; java.io.IOException; java.util.ArrayList; java.util.Arrays; java.util.Collection; java.util.List;
import javax.imageio.ImageIO; import org.mozilla.javascript.Context; import org.mozilla.javascript.Scriptable; import import import import import
cz.zcu.validationserver.gui.actions.ParametrAkce; cz.zcu.validationserver.gui.actions.VlastniAkce; cz.zcu.validationserver.gui.data.Parametr; cz.zcu.validationserver.validation.FullValidationResult; cz.zcu.validationserver.validation.ValidationInfo;
/** * Vlastni akce do weboveho rozhrani validatoru * Porovnava zdrojovy PNG obrazek (nahrany v domene) s prvnim PNG obrazkem * v pracovnim adresari momentalni validace. * (Pokud se odevzdava .jar, predpoklada se, ze se v drivejsim kroku rozbali ) * Vytvoreno pro predmet KIV/OOP *
@author Duong Manh Hung, [email protected] / public class PorovnatPNG implements VlastniAkce { * *
public void execute(ValidationInfo info, FullValidationResult result, Scriptable scope, Context jsContext, Collection<Parametr> parametry) { File workDir = info.getWorkDir(); String sampleImage = info.getDomain().getDomainProperties().getProperty(”image.sample name” ); if (sampleImage.isEmpty()) { result.addError(”Neni definovana vlastnost image.sample name.”); } // Existuje vzorovy obrazek? File validationImage = new File(workDir, sampleImage); if (! validationImage.exists()) { // vzorovy obrazek neexistuje ! result.addError(”Vzorovy ´ aobrzek pro validaci nebyl nalezen.”); return; }
47
Uk´azka extern´ı vlastn´ı akce
File screenshot = new File(workDir, ”screenshot.png”); if (! screenshot.exists()) { // png obrazek neni v odevzdavanem jaru result.addError(”Nebyl nalezen vygenerovay screenshot.”); return; } Image sample = null; try { sample = ImageIO.read(validationImage); } catch (IOException e) { result.addError(”Pri nacitani vzoroveho obrazku nastala chyba.”); return; } Image comparedImage = null; try { comparedImage = ImageIO.read(screenshot); } catch (IOException e) { result.addError(”Pri nacitani odevzdavaneho obrazku nastala chyba.”); return; } PixelGrabber grab1 = new PixelGrabber(sample, 0, 0, −1, −1, false); PixelGrabber grab2 = new PixelGrabber(comparedImage, 0, 0, −1, −1, false); // Prevod obrazku na pole pixelu int [] data1 = null; int [] data2 = null; try { if (grab1.grabPixels()) { int width = grab1.getWidth(); int height = grab1.getHeight(); data1 = new int[width * height]; data1 = (int[])grab1.getPixels(); } } catch (InterruptedException e) { e.printStackTrace(); return; } try { if (grab2.grabPixels()) { int width = grab2.getWidth(); int height = grab2.getHeight(); data2 = new int[width * height]; data2 = (int[])grab2.getPixels(); } } catch (InterruptedException e) { e.printStackTrace(); return; } if (Arrays.equals(data1, data2)) { result.addInfo(”Graficky vystup je v poradku.”); } else { result.addError(”Graficky vystup neodpovida zadani.”);
48
Uk´azka extern´ı vlastn´ı akce
int width = grab1.getWidth(); int height = grab1.getHeight(); int i = 0, j = 0; int [] diffData = new int[width int pixel;
*
height];
for (j = 0; j < height; j++) { for (i = 0; i < width; i++) { if (data1[i + j*width] == data2[i + j*width]) { pixel = data1[i + j*width]; diffData[i + j*width] = brighten(pixel); } else { diffData[i + j*width] = markDifference(); } } } MemoryImageSource mis = new MemoryImageSource(width, height, diffData, 0, width); Toolkit tk = Toolkit.getDefaultToolkit(); Image img = tk.createImage(mis); BufferedImage bufferedImage = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = bufferedImage.createGraphics(); g2.drawImage(img, null, null); String destinationPath = info.getDomain().getDomainProperties().getProperty(” html output dir”); destinationPath += ”/screenshots”; File imagesFolder = new File(destinationPath); imagesFolder.mkdir(); String diffImage = String.valueOf(”Diff ” +System.currentTimeMillis()) + ”.png”; try { ImageIO.write(bufferedImage, ”png”, new File(destinationPath + File.separator + diffImage)); } catch (IOException e) { result.addError(”Obrazek s rozdily se nepodarilo ulozit . ”) ; return; } String imageUrl = destinationPath.replace(”/var/www”, ”http://vs.kiv.zcu.cz”); result.addInfo(”Rozdily oproti spravnemu obrazku.”); } }
/** * Urcuje jak bude zvyrazneny odlisny pixel . *
@return ARGB hodnoty zvyraznovaci barvy. / private static int markDifference() { int pixel = 0xff000000; int red = 244; int green = 34; int blue = 58; * *
49
Uk´azka extern´ı vlastn´ı akce
red = red << 16; green = green << 8; pixel = pixel | red | green | blue; return pixel; } /** * Zesvetleni pixelu . *
@param pixel Momentalne zpracovavany pixel. @return ARGB hodnoty zesvetlenyho pixelu. */ static int brighten(int pixel) { int red = (pixel >> 16) & 0xff; int green = (pixel >> 8) & 0xff; int blue = (pixel) & 0xff; * *
float [] hsbVals = Color.RGBtoHSB(red, green, blue, null); // Zmena saturace a svetlosti Color brighter = Color.getHSBColor(hsbVals[0], 0.2f * hsbVals[1], 0.5f
*
(1f + hsbVals[2]));
int redModified = brighter.getRed(); int greenModified = brighter.getGreen(); int blueModified = brighter.getBlue(); redModified = redModified << 16; greenModified = greenModified << 8; int pixelModified = pixel & 0xff000000; pixelModified = pixelModified | redModified | blueModified | greenModified; return pixelModified; } public String getNazev() { return ”Porovnat PNG (KIV/OOP)”; } public List<ParametrAkce> getParametry() { ArrayList<ParametrAkce> list = new ArrayList<ParametrAkce>(); return list; } public String getPopis() { return ”Akce a ´´ aporovnv y ´vygenerovan screenshot se y ´vzorovm ´ aobrzkem.”; } public String getHelp() { String help = ”Kontextova napoveda: Vlastni akce \”Porovnat PNG (KIV/OOP)\”
”; help += ”Akce slouzi k porovani studentova obrazku se vzorovym.
”; help += ”Pokud se odevzdava JAR soubor, musi byt nejdrive rozbalen pomoci \”Rozbal ZIP \”.
”; help += ”Aby tato akce fungovala, je treba do \”domain.xml\” teto domeny dopsat vlastnost ( pres WinSCP):
”; help += ”<entry key=\”image.sample name\”>, kde hodnota je nazev vzoroveho obrazku i s priponou. ”; help += ”Napr. vzor.png
”; help += ”Vzorovy obrazek se nahraje pres \”Nahrat vzorovy obrazek\”. (Na server se nahrava .zip soubor, kde je slozka,”; help += ”ve ktere je samotny vzorovy obrazek.)
”;
50
Uk´azka extern´ı vlastn´ı akce
return help; } public String getId() { return ”PorovnatPNG”; } public String getKategorii() { return KAT_SOUBOR; }
}
51
C CD Readme [Dokumentace] Sloˇzka obsahuje pdf verzi bakal´ aˇrsk´e pr´ace a zdrojov´e tex soubory.
[Dom´ eny KIV-OOP] Obsahuje jednotliv´e konfigurace validaˇcn´ıch dom´en KIV-OOP. V t´eto sloˇzce jsou tak´e odevzdan´e u ´lohy student˚ u z let 2011/2012 a 2010/2011, kter´e slouˇzily jako testovac´ı data. Pro nasazen´ı na ostr´ y server staˇc´ı pˇrekop´ırovat dom´eny ze souboru Uzivatel.xml do souboru webov´eho rozhran´ı s naˇsimi jednotliv´ ymi dom´enami /home/validator/tomcat/webapps/ROOT/WEB−INF/data/nasOrionLogin.xml
a pˇrekop´ırovat dom´eny z CD na server /home/validator/validator/data/domains
V domain.xml je pak jeˇstˇe nutno zmˇenit poloˇzky: <entry key=”html output dir”> <entry key=”html output url”>
aby odpov´ıdaly cest´am na ostr´ y validaˇcn´ı serveru. [Moduly] Ve sloˇzce jsou potˇrebn´e knihovny pro vytvoˇren´ı modul˚ u a mnou vytvoˇren´e moduly vˇcetnˇe jejich zdrojov´ ych k´od˚ u.
[Ostatn´ı n´ astroje] Putty, WinSCP, PMD, UMLet
52