Skip to main content

Full text of "Io programmo 106"

See other formats


MICROSOFT POWERSHELL 

QUASI COME LA BASH DI UNIX. ECCO COME SI 
USA IL LINGUAGGIO DI SCRIPTING DI WINDOWS 



Rivista + "Le grandi guide di ioProgrammo" n°6 a € 12,90 in più 



SI RIVISTA+LIBRO+CD €9,90 



VERSIONE STANDARD 



RIVISTA+CD €6,90 



R0GRAMM0 



PER ESPERTI E PRINCIPIANTI 



FATTI LA TUA 
SMART CARD 

Dalla carta di credito alla scheda del telefono, 
ecco come si programmano 
i chip del futuro 

TEORIA L'architettura 
e gli standard di riferimento 

STRUMENTI . 

Il platform invoke: la porta 



d'accesso verso i circuiti 

PRATICA Crea un'applicazione 
che funziona solo se la tua carta 
è inserita nel lettore 



CODICE Gli esempi in C# e Visual Basic.NET 




. SETTEMBRE 2006 • ANNO X, N.E 



JAVA CONTROLLA 
MS OFFICE 

Da Word ad Excel: ecco 
le tecniche per manovrarli 
direttamente dal tuo codice 

SEMPRE PIÙ VELOCI 
CON I PROFILER 

Impara a usare Jrat, per sapere 
esattamente perché e dove 
il tuo software rallenta 

SNMP: LO 007 
DEL SISTEMA 

Crea un'applicazione che 
ti avverte quando qualche 
parametro è fuori controllo! 



METTI UN FTP 
NEL BROWSER 

Un completo client che gira 
dentro Explorer. Utile per 
consentire l'accesso da remoto.. 



^3^ 




PROGRAMMA IN XML 
OTTIENI UM FLASH! 

Incredibile! Il nuovo Adobe Flex 2.0 produce 
applicazioni multipiattaforma, veloci e belle 
da vedere. Quasi Java ma più facile da usare... 




I NUOVI FRAMEWORK 



ARRIVA IL GOOGLE WEB TOOLKIT 

Vuoi programmare in Ajax? Ecco lo strumento pensato dal Re della rete 
per sviluppare le applicazioni per il Web! Ti insegniamo come usarlo 



MOBILE 



SISTEMA 



PALMARI E DATABASE DEBUG SOTTO CONTROLLO 

Hai i dati su un server centrale? Ecco come Come personalizzare Visual Studio 
aggiornarli senza generare conflitti! per ottenere report avanzati 



SICUREZZA 



Privacy mai più violata grazie alla crittografia 
asimmetrica. Tutti gli algoritmi visti al microscopio 



USA L'HARD DISK 
COME DATABASE 

Crea un Custom Provider 
ed esegui Query per cercare 
informazioni sull'HD 

IL DESKTOP 

VA SU INTERNET 

Usa le Web Parts per 
poggiarci sopra gli oggetti 
e gestirli con il mouse 



PATTERN 



A LEZIONE 
DI SINGLETON 

La tecnica per non avere 
oggetti duplicati e migliorare 
l'efficienza del software 



gin 




601 06 



MASTER 9 

www.edmaster.it 



Anno X - N.ro 9 (106) - Settembre 2006 - Periodicità Mensile 

Reg. Trib. di CS al n.jo 593 del 11 Febbraio 1997 

Cod. ISSN 1128-594X 

E-mail: ioprogrammo@edma5ter.it 

http:// -' ; — 

http://www.ioprogrammo.it 

Direttore Editoriale: Massimo Sesti 

Direttore Responsabile: Massimo Sesti 

Responsabile Editoriale: Gianmarco Bruni 

Redazione: Fabio Farnesi 

Collaboratori: C. Bellucci, L. Buono, D. De Michelis, F Grimaldi, M. 



Art Director: Paolo Cristiano 



Questo mese su ioProgrammo 



Illustrazioni: M. Veltri 



:SETS.r.l. 

Realizzazione CD-Rom: Paolo lacona 

Pubblicità: Master Advertising s.rl 
Via C. Correnti, 1 - 20123 Milano 
Tel. 02 831212 - Fax 02 83121207 



Sales Director: Max Scortegagna 



Editore: Ediz™... „^,^, J .,.. l .. 
Sede di Milano: Via Ariberto, 24 - 20123 Milano 

■: C.da Lecco, zona industriale - 87036 Rende (CS) 
Presidente e Amministratore Delegato: Massimo Sesti 
"lettore Generale: Massimo Rizzo 

ABBONAMENTO E ARRETRATI 
ITALIA: Abbonamento Annuale: ioProgrammo (11 numeri) €59,90 



Libro (11 numeri) €75,90 sconto 30% sul prezzo di copertina di 
€108,90 Offerte valide fino al 30/09/06 Costo arretrati (a copia): il 

J ~n + € 5.32 spese (s - " J ' 
corriere). Prima di inviare i pagamenti, verificare la disponibilità delle 
copie arretrate allo 02 831212. 

La richiesta contenente i Vs. dati anagrafici e il nome della rivista, 
dovrà essere inviata via fax allo 02 83121206, oppure via posta a EDI- 
ZIONI MASTER via C. Correnti, 1 - 20123 Milano, dopo avere effettuato 



. cc/p n.16821878 o vai 
versamento insieme alla richiesta); 



alla richiesta); 

circuito VISA, CARTASI', MASTERCARD/EUROCARD, (in- 
viando la Vs. autorizzazione, il numero della carta, la data di scadenza e 
la Vs. sottoscrizione insieme alla richieste). 

■■■■■- rS.pAc/oF 
S.p.a. c/c 01 000 000 5000 ABI 03032 CAB 80880 CIN Q (inviando copia 
' ' " està). 

SE PREGA DI UTIUZZARE IL MODULO RICHIESTA ABBONAMENTO POSTO 
NELLE PAGINE INTERNE DELLA RIVISTA. L'abbonamento verrà attivato sul 



zioni che ne limitassero la fruizione da parte dell'utente, è prevista 

"ito. 
La sostituzione sarà effettuata se il problema sarà riscontrato e 



in edicola e nei punti vendita autorizzati, facendo fede il timbro 



Inviare il CD-Rom difettoso in busta chiusa a: 

, rt „, c™™„n:™* i/i, cr ti, 1 - 20123 Milano 



Servizio Abbonati: 



8 tei. 02 831212 



abbonati @ed master. 



Stampa: Arti Grafiche Boccia S.p.a. Via Tiberio Felice, 7 Salerno 
Stampa CD-Rom: Neotek S.r.l. - C.da Imperatore - Bisignano (CS) 



Via Vitorchiano, 81 - Roma 

Finito di stampare nel mese di Agosto 2006 

Nessuna parte della rivista può essere in alcun modo riprodotta senza 

autorizzazione scritta della Edizioni Master. Manoscritti e foto originali, 

anche se non pubblicati, non si restituiscono. Edizioni Master non sarà 

in alcun caso responsabile per i danni diretti e/o indiretti derivanti 

dall'ulilizzo dei programmi contenuti nel supporto multimediale 



fassppisgj 



Computer Bild Italia, Computer Games Gold, Digital |apan Magazine, 



Games, Filmteca in DVD, Giochi e Programmi per il tuo telefonino, 
GolOnLine Internet Magazine, Guide di Win Magazine, Guide 
Strategiche di Win Magazine giochi, Home Entertainment, Horror 



web.l Filmissimi in DVD, I Libri di Quale Computer, I Mitici all'Italiana, 



mia Videoteca, Le Femme Fatale del Cinema, Le Grandi Guide di lo 

i PI, M 

Nightmare, Office Magazine, Play Generation, Popeye, PC junior, PC 



dvd, Thriller Mania, Win Iunior, Win Magazine Giochi, Win Magazine, 
Le Collection. 



gì» A.NjyL 

p ! z ! 9 N ! IT™"" 
AASTER W 



▼ FRAMEWORK EVOLUTION 



Così la vera rivoluzione del momento sembra essere 
l'annuncio del rilascio di una versione Beta dello 
Zend Framework. Ora non è che si tratti di un 
annuncio sostanziale, esistono già tonnellate di 
classi che mirano ad estendere le già elevate poten- 
zialità di PHP Si tratta però di un annucnio impor- 
tante perché a farlo è ZEND, principale promotrice 
dello sviluppo del linguaggio. 
La novità è soprattutto di marketing. Ricalcando un 
po' le orme del .NET framework almeno nel nome, 
si vuole lasciare intendere che quello che esiste 
sopra il livello delle dll di .NET e cioè una serie di 
classi omogenee tese a rendere semplice la vita al 
programmatore, esiste in realtà anche per PHP e da 
molto più tempo. Ora non è che fra i due linguaggi 
ci sia concorrenza. PHP rimane il leader indiscusso 
delle Web application di medio livello su Internet. E' 
dal punto di vista delle Business application che 
però si combatte la vera battaglia. In questo settore 
PHP non ha la stessa diffusione di .NET o di JSP e 
tuttavia è proprio qui che risiedono i fondi che ser- 
vono per mantenere in attivo società come ZEND e 
che devono essere utilizzati per finanziare lo svilup- 



po di PHP Dal punto di vista strettamente tecnico, 
lo ZEND framework si configura come un insieme 
di classi realmente ben strutturato. Sono sufficienti 
poche righe di codice per programmare un Web 
Service o per creare un report in formato PDF. Zend 
ha decisamente fatto un buon lavoro. Cosa manca 
dunque a PHP? Probabilmente soltanto un editor 
visuale del calibro di Visual Studio. Ma in realtà la 
forza di PHP sta probabilmente nella flessibilità, per 
cui legarlo strettamente a un tipo di editor sarebbe 
probabilmente un boomerang. 
Dove voglio arrivare con questo mio ragionamen- 
to? Voglio semplicemente mostrare ai programma- 
tori quanto possa essere ampia la scelta degli stru- 
menti disponibili sul mercato e che tendono a 
migliorare la produttività del nostro lavoro. Molto 
probabilmente la questione è scegliere sempre 
quello giusto per le nostre esigenze. Ormai il merca- 
to è talmente vasto che affidarsi a un framework 
come quello di Zend significa non dover riscrivere 
da zero i 1 proprio codice. L'importante è avere la 
forza di volontà di imparare un nuovo framework! 
Fabio Farnesi ffarnesi@edmaster. it 




All'inizio di ogni articolo, troverete un simbolo 
che indicherà la presenza di codice e/o software 
allegato, che saranno presenti sia sul CD (nella 
posizione di sempre \soft\codice\ e \soft\tools\) 
sia sul Web, all'indirizzo 
http://cdrom.ioprogrammo.it. 



FATTI LA TUA 
SMART CARD 

Dalla carta di credito alla scheda del 
telefono, ecco come si programmano 
i chip del futuro ti 







• TEORIA: L'architettura 
e gli standard 
di riferimento 

• CODICE: gli esempi 

in C# e Visual Basic.NET 



PRATICA: Crea un'applicazione 
che funziona solo se la tua carta 
è inserita nel lettore 







*> 



l_ l niuThii kvn.ihi.L'ii'ii I 
HDi.K7DdEl18f1ZttM5 www.itportal.it 



• STRUMENTI: Il platform invoke 
e la porta d'accesso verso i circuiti 



pag. 14 



Questo mese su ioProgrammo 



PROGRAMMA IN XML 
OTTIENI UN FLASH! 



Il nuovo Adobe Flex 2.0 produce applicazioni multipiattaforma, 
veloci e belle da vedere. Quasi Java ma più facile da usare 

pag. 62 



IOPROGRAMMO WEB 



Da XML a Flash passando per Flex . . 
pag. 22 

Una guida passo passo alla nuova versione del 
prodotto di Adobe dedicato agli sviluppatori. 
Vedremo come in un modo rapido e visuale si 
possono sviluppare interfacce che funzionano 
sia per Web sia standalone e per tutte le 
piattaforme 

Programmare Ajax secondo... 
Google! pag. 28 

Al gran numero di Framework per sviluppare 
applicazioni Web in tecnologia Ajax non pote- 
va mancare un toolkit sviluppato dal gigante 
di Internet. Il Google Web Toolkit si presenta 
con qualche carta in più. Vediamo quale 

Usare il Browser come desktop 
pag. 34 

Una delle novità più interessanti del 
Framework .Net 2.0 è sicuramente quella 
delle "Web parts". Si tratta di un metodo 
che consente ad un utente di costruire 
dinamicamente una pagina Web adattan- 
dola alle proprie preferenze... 



MOBILE 



Sincronizzare i dati tra server e 
palmare pag. 60 

Se abbiamo una rete di palmari, i dati 
presenti in un dispositivo devono 
sicuramente essere sincronizzati con un 
database centrale. Scopriamo come 
gestire upload multipli evitando 
eventuali conflitti 



DATABASE 



Dal linguaggio SQL agli oggetti 

pag. 40 

Indagheremo più a fondo nelle potenzialità 
del framework Hibernate. Presenteremo un 
plugin che ci permetterà di sviluppare Gui 
all'interno di Eclipse. Impareremo come i data- 
base possano essere trattati come oggetti 

Custom data provider con .Net 

pag. 46 

Implementiamo un componente intermedio 
che consente di accedere a qualunque tipo di 
dato utilizzando gli stessi metodi ed interfacce 
e variando solo pochi parametri 



SISTEMA 



Ottimiziamo il codice con Jrat 
pag. 66 

/ profiler sono strumenti molto 
interessanti che consentono di ottenere 
una misura delle prestazioni precisa 
mentre il sofware è in esecuzione. 
Sfruttando queste tecniche è possibile 
ottenere miglioramenti significativi... 

Java come pilota Word come motore 
pag. 72 

Siamo abituati a pensare a Java come un 
mondo completamente staccato da 
quello dei software che girano sui 
sistemi microsoft. Tuttavia esistono 
soluzioni che possono rendere i due 
mondi molto vicini... 

Facilitare il debug con i visualizer 
pag. 76 

Non tutti sanno che visual studio 2005 
offre possibilità di personalizzazione 
praticamente infinite, in questo articolo 
illustreremo come migliorare il debug di 
strutture proprietarie , utilizzando 
controlli specifici 



RUBRICHE 



NETWORKING 



Metti un FTP nel 
tuo Browser 

pag. 52 

Creiamo un client FTP che 
vive all'interno di Explorer. 

Utilissimo per uploadare file 
in remoto senza scomodare 

^ programmi di terze parti 



Gli allegati di ioProgrammo 

pag. 6 
// software in allegato alla rivista 

Il libro di ioProgrammo 

pag. 7 
// contenuto del libro in allegato 
alla rivista 

News pag. 10 

Le più importanti novità del 
mondo della programmazione 

Software pag. 106 

/ contenuti del CD allegato ad 
ioProgrammo. 



Il Namespace My semplifica la vita 
pag. 82 

In questo articolo illustreremo alcune 
caratteristiche del nuovo framework 2.0 
che consentono di accedere rapidamente 
a informazioni di sistema o altri percorsi 
di progetto, senza troppe complicazioni. 



NETWORKING 



SNMP: sistema 
sotto controllo 

pag. 88 

Java dispone di alcune classi 
che consentono di interfaccia- 
re le nostre applicazioni con 
SNMP 



Arriva la Shell di Windows 
pag. 97 

Gli utenti Unix sono abituati a lavorare a 
riga di comando. Dopo tanti anni anche 
Microsoft ha deciso di fornire strumenti 
avanzati di automazione per la gestione 
del sistema basati su Shell. Vediamo 
quali 

Singleton Pattern come usarlo? 
pag- 104 

Non molti conoscono questa tecnica di 
programmazione. Tuttavia si tratta di un 
tassello fondamentale per non 
inciampare in oggetti duplicati e 
strutture poco efficienti. Impariamo cosa 
e come funziona 



QUALCHE CONSIGLIO UTILE 

I nostri articoli si sforzano di essere 
comprensibili a tutti coloro che ci 
seguono. Nel caso in cui abbiate 
difficoltà nel comprendere esattamente 
il senso di una spiegazione tecnica, è 
utile aprire il codice allegato all'articolo 
e seguire passo passo quanto viene 
spiegato tenendo d'occhio l'intero 
progetto. Spesso per questioni di spazio 
non possiamo inserire il codice nella 
sua interezza nel corpo dell'articolo. Ci 
limitiamo a inserire le parti necessarie 
alla stretta comprensione della tecnica. 







http://forum.ioprogrammo 



£) 



Le versioni di ioProgrammo 




ROGRAMMO 



FATTILATUA 
SMART CARD 

Dalln <ar%* di cadila Blki «hed., del — 
ceto «me si programmai» 
I chip dd futura 



igmtw 



Crea un" . . 

rherurtWHUiùfc» t| tua tali 
fruiserrtand aerare 

Vi-,ujI K «ir !JET 







'="?■- PROGRAMMA IN XML 
OTTIENI UN FLASH! 



' WEB TOOLKIT 

"•» n«w l ^™^ M ™~" ito penMW **1 il* *W>" W - 




RIVISTA + CD-ROM 

in edicola 



FLEX 2.0 

Il nuovo Framework di Adobe 



Straordinario! Non ci sono 
parole per descrivere questo 
nuovo prodotto della linea 
Adobe che in un sol colpo fa 
piazza pulita di un vecchio 
modo di pensare alle appli- 
cazioni per inventarne uno 
tutto nuovo, semplice ed 
estremamente potente. Chi 
ha letto questo numero di 
ioProgrammo sa già come 
funziona Flex 2.0. Si scrive 
un programma utilizzando 
un dialetto di XML, lo si da 
in pasto al compilatore e si 
ottiene in uscita un file SWF 
ovvero utilizzabile dal noto 
player Flash di macromedia. 
Quali sono i vantaggi? Ce ne 
sono diversi, i più facili da 
intuire sono la completa 



indipendenza dal sistema 
operativo senza per questo 
doversi affidare alla macchi- 
nosità di java. La possibilità 
che la stessa applicazione 
possa girare praticamente 
senza modifiche sia in modo 
standalone che nel browser. 
La possibilità di sviluppare 
interfacce dall'aspetto omo- 
geneo e molto altro... 



Prodotti del mese 



Ajax Pro 
Starter Kit 

Per iniziare facilmente 
con Visual Studio 

Da qualche tempo non si fa altro 
che parlare di Ajax. Si tratta della 
nuova tecnologia che consente di 
realizzare pagine web dinamiche 
che non necessitano del reload per 
aggiornare i dati. Come potete 
intuire si tratta di un'innovazione 
senza precedenti che consente di 
realizzare applicazioni Web con 
comportamenti molti simili alle nor- 
mali applicazioni Desktop. Visual 
Studio 2005 dispone della tecnolo- 
gia degli Starter Kit, che consente 
di iniziare un progetto partendo da 
una sorta di template che ne facilità 
l'avvio. Il tool che vi presentiamo è 
appunto lo starter kit che consente 
di iniziare a sviluppare un progetto 
Web in ASP.NET ed in tecnologia 
.NET. Si tratta senza dubbio di un 
valido aiuto per sviluppare le pro- 
prie Web Application utilizzando 
questa tecnica 

[pag.106] 




Atlas Control 
Toolkit 

/ migliori componenti per lo 
sviluppo Web 

Nasce da una collaborazione 
fra Microsoft e i creatori 
originali, questo interessante 
pacchetto che si propone di 
fornire al programmatore una 
serie di componenti "client" 
adatti a favorire lo sviluppo di 
Web Application. All'interno 
del pacchetto si trova una ricca 
collezione di esempi che fanno 
uso di una quindicina di nuovi 
controlli, infine c'è un SDK che 
consente di estendere 
ulteriormente Atlas che in 
questo modo si configura come 
un vero e proprio Framework 
per lo sviluppo. La quantità e 
la qualità dei controlli è tale 
che utilizzando questo 
pacchetto si ottengono 
vantaggi sia in relazione alla 
produttività sia in relazione 
all'eficienza 

[pag.106] 



"Th«'BaHS"' 


— ..T.7..?. 




*— - 


.-"^SZ. i^i^-.^'.:. 1 ■r-ng^u 


jgXirz::: ■*" 






lltlBBasESsE— 



Hibernate 3.2.0 

Trasforma i da dati da SQL ad 
Oggetti 

Ormai lo sappiamo abbiamo letto 
tutti gli articoli di ioProgrammo su 
Hibernate, pensare in termini di 
query e dati SQL non è più conve- 
niente! Disponiamo di oggetti e 
di classi, non possiamo continua- 
re a lavorare in modo disomogeneo 
trattando i dati SQL in maniera se- 
parata dal resto del flusso del pro- 
gramma. E per mappare i dati da 
SQL ad oggetti abbiamo bisogno di 
un tool. Il primo ed ancora ades- 
so Leader di questo settore è Hi- 
bernate, attraverso il quale riu- 
sciamo ad ottenere comodamente 
i risultati voluti. Il meccanismo è 
semplice, si scrivono alcuni file 
XML che rappresentano la descri- 
zione del nostro DB, si danno in 
pasto ad Hibernate che provvede 
a creare una serie di classi e di og- 
getti utili a gestire il database, li- 
berandoci dal vincolo di doverli 
progettare a mano 

[pag.107] 




PHP 5.1.4 

// linguaggio più utilizzato per la 
programnazione di internet 

Se seguite ioProgrammo o più 
semplicemente siete dei pro- 
grammatori Web, o ancora molto 
più semplicemente navigate su 
Internet, non potete non sapere 
che cosa è PHP. Si tratta del lin- 
guaggio con il quale sono svilup- 
pate la maggior parte delle 
applicazioni internet esistenti. 
Quasi tutto il software per il web 
si regge su PHP. La curva di 
apprendimento è bassissima, le 
funzionalità esposte elevatissi- 
me, certamente se avete inten- 
zione di sviluppare per il web 
non potrete fare a meno di pro- 
vare anche questo linguaggio 
come base per le vostre applica- 
zione. Attualmente la versione 
5.1.4 espone un modello ad 
oggetti piuttosto completo che 
rende PHP un linguaggio moder- 
no dalla curva di apprendimento 
molto rapida e persino didattico 
[pag.107] 



»» 






uu=à-. 




ssxr.=. i =i£:--^Fr..-=z=^: *±Si 


W- 




fess-s^ jb- 


saStS'SSKssIBP — 





pv 6 /Settembre 2006 



http://www.ioprogrammo.it 



Le versioni di ioProgrammo 




MICROSOFT POWERSHELL 



ROGRAMMO 



i ■ ■'*, .',1, iii^^^^^^ ^^^ ^^^^~ 

FATTIJLATUA 
SMART CARD 

Dalla carta di credito alla scheda del " 
ecco come si programmano 

I chip del futuro 

TEORIA L'architettura 
e gli standard di riferimento 

STRUMENTI ^ 

II platform invoke; la porta dfl 
d'accesso verso i circuiti 
PRATICA Crea un'applicazione 
che funziona solo se la tua carta 
è inserita nel [««ore 

Gli es«npi in O» e Visual Basic.NET 



PROGRAMMA IN XML 
OTTIENI UN FLASH! 

Incredìbile! li nuovo Adobe Flex 2.0 produce 
olk a? iti m multìpiattaforma, veloci e belle 

l Quasi Java ma più facile da oiare... 




JAVA CONTROLLA 
MS OFFICE 

Di Word J<3 b(« t«a 

lelCcnHL'fW pw rTtaFKrt"*1l 

| dipoli a import e dal H» *HJKt 

, SEMPRE PIÙ VELOa 
CON \ PROFILER 

...... ... , .... ira li- ■ ..11-11 



5NMP: LO 007 
DEL SISTEMA 

Cr*j un.'appllcatiW* * he n 
auverlfi quando qualche 
paMnMtra * fifO" ffMi.frUlO 1 



RIVISTA + LIBRO 
+ CD-ROM 

in edicola 




- ouìasiS 



.""■"•'^«.".S""'"»™"' 



1 .JS-T»"" 




I contenuti del libro 



Lavorare con C++ 



C++ è il linguaggio più amato da chi 
programma a basso livello. Per certi versi 
può considerarsi il padre di tutti i linguaggi. 
Sicuramente quello a cui tutti si sono ispirati per 
creare nuovi paradigmi di programmazione. E' 
sicuramente un linguaggio multipiattaforma. Chi 
lo padroneggia può ritenere a ragione di conoscere 
i sistemi in modo profondo. In questo libro 
"Roberto Allegra" ci mostra i concetti avanzati del 
linguaggio. Si tratta di un viaggio affascinante, 
condotto spesso al bordo della conoscenza 
profonda delle macchine e del funzionamento dei 
sistemi operativi. Un libro da leggere, non solo e 
soltanto per impadronirvi delle tecniche 
necessarie a programmare il C++, ma anche per 
comprendere a fondo certi meccanismi 
dell'informatiche che a molti risultano oscuri 



LE STRUTTURE E LE FUNZIONI AVANZATE. 
PER SFRUTTARE AL MASSIMO IL PADRE 

DI TUTTI I LINGUAGGI 

• Gestione dinamica degli oggetti 

• Utilizzare le eccezioni 

• Le librerie e i canali standard 

• Stringhe e canali 



http://www.ioprogrammo.it 



Settembre 2006/7 ► 



I contenuti multimediali 



GLI ALLEGATI DI IOPROGRAMMO 



Web Development 



Sviluppare Web Application pro- 
fessionali, in grado di soddisfare 
le esigenze sempre più complesse di 
un mercato in continua evoluzione 
implica un elevato grado di attenzio- 
ne da dedicare ad ogni singolo parti- 
colare di un'applicazione. Non è suf- 
ficiente sviluppare soluzioni che ri- 
solvano un problema. E' invece ne- 
cessario sviluppare software che sia 
stabile sicuro, efficace e veloce. In que- 
sto contesto ASENET si propone co- 
me un framework che dota lo svilup- 
patore di strumenti avanzati, che in- 
globano per loro natura le caratteri- 
stiche richieste. Conoscere questo ge- 
nere di strumenti significa compiere 
il necessario salto di qualità per esse- 
re competitivi sul mercato dello svi- 



luppo. In questi tre Webcast MSDN 
vengono affrontate due delle princi- 
pali tecnologie coinvolte nello svi- 
luppo di Web Application professio- 
nali. Nel primo caso si parla di intera- 
zione con i database, là dove un con- 
trollo minuzioso su come i dati ven- 
gono manipolati garantisce una mag- 
giore efficacia all'applicazione. Nel se- 
condo caso si parla di deployment di 
una soluzione, operazione che a mag- 
gior ragione per .NET si presenta come 
molto delicata. Prima perché .NET 
porta in sé un'innata propensione al- 
la sicurezza, che però deve essere sup- 
portata da un deployment efficace, se- 
condo perché il deployment può av- 
venire in diverse situazioni non sem- 
pre omogenee. 



I VIDEOCORSI PER PROGRAMMARE BENE 

^WEBCAST 

«^UFFICIALI MICROSOFT 

Imperdibili! Per imparare 

a programmare applicazioni Web 

Dinamiche con supporto ai database 

• ASP.NET 2.0 DataBinding 

• ASP.NET 2.0 DataBinding avanzato 



ASP.NET 2.0 Deployment di una 
soluzione 






INFORMAZIONI SU MSDN WEBCAST 

http://www.microsoft.it/msdn/webcast_msdn 
http://forum.ioprogrammo.it 



FAQ 



Cosa sono i Webcast MSDN? 

MSDN propone agli sviluppatori una serie di eventi gratui- 
ti online e interattivi, che approfondiscono le principali 
tematiche relative allo sviluppo di applicazioni su tecnolo- 
gia Microsoft. Questa serie di "corsi" sono noti con il 
nome di Webcast MSDN. 

Come è composto tipicamente 
un Webcast? 

Normalmente viene presentata una serie di slide commen- 
tate da un esperto di tecnologie Microsoft. A supporto 
di queste presentazioni spesso vengono realizzate 
delle demo in presa diretta che mostrano dal vivo come 
usare le tecnologie oggetto del Webcast 

Come mai nei webcast allegati 
alla rivista si parla di chat e 
di altri strumenti interattivi? 

La natura dei Webcast è quella di essere seguiti online e in 
tempo reale. Durante queste presentazioni in diretta ven- 
gono utilizzati strumenti molto simili a quelli della forma- 
zione a distanza. E' possibile porre domande in presa diret- 
ta al relatore oppure partecipare ai sondaggi che vengono 
proposti. In questo modo gli sviluppatori possono aggior- 
narsi e approfondire i temi di loro interesse con maggiore 
efficacia. I Webcast riprodotti nel CD di ioProgrammo, pur 
non perdendo nessun contenuto informativo, per la natura 



asincrona del supporto non possono godere dell'interazione 
diretta con il relatore. 

Come mai trovo i Webcast 
su ioProgrammo 

Come sempre ioProgrammo cerca di fornire un servizio ai 
programmatori italiani. Abbiamo pensato che poter usufruire 
dei Webcast MSDN direttamente da un CD rappresentasse un 
ottimo modo di formarsi comodamente a casa e nei tempi desi- 
derati. Lo scopo tanto di ioProgrammo, quanto di Microsoft è 
infatti quello di supportare la comunità degli sviluppatori ita- 
liani con la più ampia gamma di strumenti di formazione e 
aggiornamento. 

Su ioProgrammo troverò 
tutti Webcast MSDN? 

Ne troverai sicuramente una buona parte. Direttamente sul 
sito MSDN potrai consultare il calendario dei prossimi 
webcast a cui iscriverti per seguirli in diretta oppure con- 
sultare l'archivio delle registrazioni di quelli già realizzati. 
L'indirizzo per saperne di più è 

www.microsoft.it/msdn/webcast msdn, segnalo nel tuo 
bookmark, non può mancare! 

L'iniziativa sarà ripetuta sui prossimi 
numeri? 

Sicuramente sì, alla prossima. 



»> 8 /Settembre 2006 



http://www.ioprogrammo.it 



NEWS T 



News 



MICROSOFT 
REGALA VIRTUAL PC 

La virtualizzazione è la vera novità 
degli ultimi anni per noi program- 
matori. Sia VMWare sia Virtual PC 
consentono di far girare più sistemi 
operativi in una sorta di SandBox. 
Questo ci permette di testare il 
software nel migliore dei modi su 
più sistemi e sotto diverse condizio- 
ni senza per questo dover continua- 
mente formattare la macchina su cui 
eseguiamo lo sviluppo. 
Recentemente VMWare ha annun- 
ciato il rilascio gratuito del proprio 
Player. Un passo ancora maggiore lo 
ha compiuto Microsoft annunciando 
di voler distribuire gratuitamente il 
proprio Virtual PC 2004. Questa 
mossa è sicuramente da intendersi 
come il tentativo di conquistare 
nuove fette di mercato in vista del- 
l'arrivo di Virtual PC 2007. Non è 
chiaro se la nuova versione sarà 
anche essa gratuita. Sicuramente 
la volontà è quella di rivaleggiare ad 
armi pari con il concorrente VMWare 
che fino ad ora è il leader di merca- 
to. Vedremo come finirà questa 
entusiasmante sfida 



SYMBIAN OS 
EVOLUZIONE 9.3 

n un momento di forte espansione 
dei pocket PC dovuta principalmen- 
te alla buona riuscita di Windows Mo- 
bile 5.0, il rivale Symbian non poteva 
stare a guardare. Così è recente il rilascio 
della nuova versione di Symbian OS, 
la 9.3 che contiene alcune novità lar- 
gamente attese. Finalmente è stato 
incluso nel sistema il supporto per il 
Wi-Fi. Sulla base di questa è stato poi 
aggiunto un supporto per il Voip, in 
questo modo gli utenti dovrebbero 
poter scegliere se telefonare in modo 
tradizionale oppure attraverso il Wi- 
reless. Novità molto importanti per 
noi sviluppatori è invece rappresen- 
tata dall'arrivo di alcuni strumenti di 
sviluppo basati sull'onnipresente Ecli- 
pse, e che dovrebbero garantirci una 
maggiore semplicità di sviluppo. Que- 
ste due importanti innovazioni do- 
vrebbero fronteggiare la crescita di 
Windows Mobile 5.0 



L'ACCESSIBILITÀ 
DELLA DISCORDIA 



E' ancora la legge sull'accessibilità 
dei siti web a provocare un 
intenso dibattito nel parlamento 
come negli addetti ai lavori. La 
legge attuale è stata largamente 
disattesa, sia per motivi legati ad 
una certa "fumosità" in alcuni para- 
grafi della stessa, sia per la presen- 
za di alcune "scappatoie" che 
hanno favorito i soliti furbi. Così 
Cesare Campa e Antonio Palmieri 
deputati di forza Italia si sono fatti 
carico di una nuova proposta elabo- 
rata ancora una volta con la colla- 
borazione di IWA/HWG. Le questio- 
ni su cui si dibatte sono essenzial- 
mente due. La prima riguarda l'ob- 



bligo del rispetto delle norme di 
accessibilità anche per i progetti 
nati come intranet. L'attuale legge 
infatti reca un buco normativo tale 
che molti progetti della P.A. nati 
all'interno delle strutture sono riu- 
sciti ad arrivare ai cittadini senza 
curarsi degli obblighi di accessibilità 
proprio perché l'attuale legge non 
prevede il rispetto della normativa 
per i progetti nati come intranet. In 
questo modo molte P.A. hanno 
potuto far nascere i progetti come 
interni alla propria struttura, espor- 
tandoli poi all'esterno senza per 
questo doversi sottoporre al con- 
trollo del CNIPA. 



GOOGLE VS PAYPAL 



Tutti conoscono Pay- 
Pal, il sistema di pa- 
gamento elettronico più 
diffuso in america e che 
sta lentamente guada- 
gnando posizioni anche 
in Italia. Il funzionamento 
è semplice. Ci si iscrive 
a Paypal, e si lasciano i 
dati della propria carta 
di credito. A questo pun- 
to non è più necessario 
fornire il proprio nume- 
ro di carta di credito a 
nessun esercente. Sarà 
sufficiente fornire il pro- 
prio identificativo di ac- 
cesso su paypal per da- 
re il via alla transazione. 
Sarà paypal stesso a fa- 
re da tramite fra gli istituti 
di credito. Questo meto- 
do si è rivelato un enor- 
me successo ed in molti 
hanno cercato di imitar- 
lo senza tuttavia riuscir- 
vi pienamente. E' adesso 



il turno di Google che ha 
appena lanciato sul mer- 
cato un sistema che pren- 
de il nome di Chekout e 
che utilizza lo stesso iden- 
tico sistema di paypal. 
Ovviamente staremo a 
vedere chi la spunterà e 
quali sono i vantaggi nel- 
l'usare l'uno e l'altro me- 
todo. Attualmente 
checkout non sembra 
avere la stessa penetra- 



zione di mercato che ha 
avuto paypal al suo lan- 
cio. Tuttavia trattandosi 
di Google possiamo 
scommettere sulla vali- 
dità del servizio. Si regi- 
strano già le prime rea- 
zioni di Ebay che è an- 
che proprietaria di Pay- 
pal e che ovviamente si 
è dichiarata molto osti- 
le all'arrivo di questo nuo- 
vo soggetto finanziario 



GodoIi* 

Chw*oui ° ff 

Fmd unum oeegfc Bui * #i 
«Kn » GMffa Oncmm ~ -» 

O—knJ mi V «Meli ■ fd .1 



Hinfeijurtii tB 




e Hjijh-o* &TK>flk Crwckwrt 



► 10 /Settembre 2006 



http://www.ioprogrammo.it 



NEWS T 



Il secondo punto di discussione riguarda 
proprio il CNIPA. Attualmente è previsto 
che questo ente provveda a monitorare 
solo le amministrazioni centrali. Il nuovo 
progetto prevede che il controllo passi al 
Corecom (comitato regionale per le 
comunicazioni) che dovrebbe poter 
monitorare anche regioni, province, ed 
enti locali. La legge è di quelle impor- 
tanti, perché una sua corretta applica- 
zione garantirebbe anche ai cittadini 
diversamente abili un corretto accesso 
alle informazioni e ai servizi contenuti in 
rete. Al di la del merito delle proposte 
che sono state effettuate, noi pensiamo 
che sia necessaria una sensibilizzazione 
su grande scala in relazione all'argo- 
mento, proprio perché le software 
house devono essere le prime responsa- 
bili nell'attuazione corretta dei regola- 
menti e soprattutto nell'applicazione 
delle regole di buon senso che rendereb- 
bero fruibili i contenuti OnLine al mag- 
gior numero di persone possibili 



ARRIVA LO ZENO FRAMEWORK 



Che a far la fortuna di 
PHP, fra le altre co- 
se, sia la sua estrema sca- 
labilità è un fatto noto. 
Chi usa PHP può scegliere 
di programmare in mo- 
do Object Oriented, in 
modo procedurale e per- 
sino in modo Fiat. A tut- 
to ciò si aggiunge un co- 
spicuo numero di pro- 
getti e classi esterne che 
ne possono estendere le 
possibilità. E' di questi 
giorni l'annuncio del ri- 
lascio di una prerelease 
dello "Zend Framework", 
in particolare della sua 
versione 0.1.4. Si tratta 
di un annuncio di parti- 
colare rilievo se si pen- 
sa che Zend è l'azienda 
principale promotrice 



dello sviluppo di PHP In 
teoria lo Zend framework 
non si distanzia di mol- 
to a livello concettuale 
dai tool già esistenti, ad 
esempio PEAR. Si tratta 
cioè di una serie di clas- 
si che lavorano sotto un 
unico "cappello". All'atto 
pratico però lo Zend Fra- 
mework si è rivelato par- 
ticolarmente potente, 
ben costruito e affidabi- 
le. Sono sufficienti un 
paio di righe di codice 
per sviluppare un Web 
Services, non molte di 
più per creare un report 
in formato PDF. Le clas- 
si presenti nello Zend 
Framework coprono so- 
stanzialmente tutti gli 
aspetti nodali dello svi- 



luppo software in am- 
biente Web. Si tratta di 
un passo importante per- 
ché adesso gli sviluppa- 
tori hanno a disposizio- 
ne uno strumento di al- 
to livello per program- 
mare le proprie applica- 
zioni. Chi vuole potrà 
sempre cominciare ad 
apprendere il linguaggio 
e iniziare a scrivere tutto 
il codice partendo dalle 
classi base, gli altri pos- 
sono imparare diretta- 
mente a usare il Fra- 
meWork e utilizzare le 
sue peculiarità per svi- 
luppare. In tutti i casi an- 
cora una volta viene pre- 
miata l'eccezionale sca- 
labilità di questo lin- 
guaggio 



WINFS ADDIO! 

Il nuovo rivoluzionario File System che 
Microsoft aveva annunciato come pun- 
to di forza del prossimo futuro Windows 
Vista non ce l'ha fatta a vedere la luce. Il 
progetto WinFS è stato annullato e non 
sarà più quest'ultimo a sostenere il File 
System divista. In realtà Microsoft non 
sembra avervi rinunciato totalmente. Se- 
condo il big di Redmond, WinFS è stato 
semplicemente "smembrato" e buona 
parte delle tecnologie che lo sosteneva- 
no saranno integrate in altri progetti. In 
pratica WinFS continuerà a vivere, ma 
non come un progetto a se stante, quan- 
to come una serie di "pillole" integrate in 
altre tecnologie. Questo almeno è quan- 
to dichiarato da Microsoft. Diversa è l'o- 
pinione degli avversari dell'azienda di 
Bill Gates. Sono in molti infatti a soste- 
nere che il progetto è stato abbandonato 
poiché diventato talmente complesso da 
non essere più gestibile. E' il classico ca- 
ne che si morde la coda, ovvero un progetto 
talmente tecnologicamente avanzato che 
la sua complessità lo rende inaffidabile 
e instabile. Nel frattempo non ci resta 
che aspettare Vista per capire se il lavoro 
fin qui svolto ha realmente dato i risul- 
tati sperati 



MICROSOFT ABBRACCIA 
L'OPENDOCUMENT 



Con una mossa a sorpresa il 
colosso di Redmond ha annun- 
ciato di stare lavorando ad un pro- 
getto OpenSource che favorisca 
l'interoperabilità fra l'ODF e 
l'OPENXML 

Fino a qualche settimana fa il rifiu- 
to di MS nei confronti di Open 
Document era netto. Secondo l'a- 
zienda di Bill Gates, l'interesse dei 
propri clienti nell'adottare l'ODF 
era basso. Oggi la posizione 
di Microsoft è radicalmente 
cambiata. £3i& 

Con questo nuovo tool si 
intende fornire ai consuma- 
tori uno strumento in grado 
di convertire i documenti da 
un formato all'altro in modo 
estremamente semplice, 
dalla linea di comando o dal- 
l'interfaccia di Office. 
Microsoft ha dichiarato di 
volere, in questo modo. 



sostenere fattivamente la tanto 
decantata interoperabilità. Tuttavia, 
questa operazione, sembra essersi 
resa necessaria anche a causa delle 
dichiarazioni del governo del 
Massachusetts che ha dichiarato di 
voler adottare proprio ODF come 
formato standard per i documenti 
della pubblica amministrazione. Il 
nuovo tool sarà compreso in Office 
2007 




http://www.ioprogrammo.it 



Settembre 2006/ 11 ► 



COVER STORY T 



Gli standard e le tecniche per utilizzare le Smart Card 



PROGRAMMARE 
LE SMART CARD 

POSSONO CONTENERE DATI. UTILIZZANO ALGORITIMI DI CRITTOGRAFIA MOLTO SICURI 
PER L'AUTENTICAZIONE. GIÀ OGGI SONO UTILIZZATE PER LA FIRMA DIGITALE. IN 
QUESTO ARTICOLO NE FAREMO UNA PANORAMICA COMPLETA... 




n 




REQUISITI 



Conoscenze richieste 



— Basi di Ot 






Windows XP/2003 .net 
Framework 2.0, 
Microsoft Visual Studio 
.NET2005 




o scopo di questo articolo è il seguente: 
impedire l'accesso ad un'applicazione a 
meno delle seguenti condizioni: 



un lettore di smart card sia connesso al 
computer 

• l'utente che desidera accedere all'applica- 
zione possieda una smart card e ne cono- 
sca il codice pin 

• Se una volta immessa la Smart Card all'in- 
terno del lettore, l'utente è in grado di inse- 
rire il codice d'accesso corretto, allora avrà 
accesso all'applicazione, altrimenti no. 

Tanto per fare un esempio tipico, è la classica 
situazione davanti alla quale ci si ritrova 
quando si preleva del denaro al bancomat. 
Inseriamo la nostra Smart Card (tessera ban- 
comat) all'interno del lettore, se siamo in 
grado di verificarne il codice Pin saremo auto- 
rizzati a compiere le operazioni, altrimenti 
no. Questo tipo di protezione è largamente 
utilizzata in una serie di contesti. Abbiamo 
fatto l'esempio del bancomat, ma considerate 
anche il caso più semplice di un impiegato 
che potrà accedere al suo terminale solo pre- 
via autenticazione con Smart Card. E ancora 
quello della cassiera di un supermercato che 
potrà far funzionare la cassa solo se autenti- 
cata dalla sua Smart Card. In uno scenario più 
futuristico, su una Smart Card si possono con- 
servare dati importanti, ad esempio i propri 
dati personali. In un futuro potrebbe essere 
sostitutiva della patente e già le camere di 
commercio italiane fanno uso di una Smart 
Card per concedere l'accesso ai propri servizi 
e per conservare la famosa "firma digitale". 



COSA SERVE 
PER INIZIARE? 

Avremo bisogno di un lettore di Smart Card e 
di qualche Smart Card di prova. Per il nostro 




Fig. 1: II lettore Omnikey Cardman nelle versioni USB 
e PCMCIA utilizzato per testare il presente articolo. 
Sulla sinistra due Smart Cartd infineon ancora vuote 

articolo abbiamo usato un lettore Omnikey 
CardMan 4040 PCMCIA acquistato presso 
Multimedia It - http://www.multimediait.it - e 
del costo di 69,00 . In alternativa sempre 
presso Multimedia It è possibile acquistare il 
CardMan 3121 che dispone di interfaccia USB 
e ha un costo di 25,00 . In realtà tutti i lettori 
di Smart Card dovrebbero funzionare con la 
tecnica proposta in questo articolo. Ma poi- 
ché come vedremo fra i vari lettori esiste 
qualche differenza, pur rimanendo la tecnica 
universalmente valida, potrebbe essere 
necessario riferirsi alla documentazione uffi- 
ciale del lettore utilizzato per avere piena 
padronanza dei codici da utilizzare. Per quan- 
to riguarda il costo delle Smart Card, sempre 
presso Multimedia It è possibile acquistarle 
ad un prezzo che varia da 18.00 ai 25.00 a 
secondo del quantitativo acquistato. 



LETTORI 

E SMART CARD 

Il lettore di Smart Card è semplicemente un 
apparecchio che consente di accedere in let- 
tura/scrittura alla Smart Card. Viceversa sulla 
Smart Card è presente un vero e proprio siste- 
ma operativo. Nel nostro caso abbiamo usato 
delle Smart Card prodotte da Infineon ed 



»> 14 /Settembre 2006 



http://www.ioprogrammo.it 



Gli standard e le tecniche per utilizzare le Smart Card ■ ▼ COVER STORY 



equipaggiate con un sistema operativo 
Sicrypt conforme alle specifiche ISO 7816-4 e 
PKCS #15, vedremo a breve cosa significano 
queste sigle. Tutte le informazioni sul Sycript 
sono comunque disponibili sul sito 
http://www.infineon.com. 

Un sistema operativo per Smart Card assolve 
a due funzioni particolari: gestire un file 
system con una struttura conforme alle speci- 
fiche di cui sopra, esporre dei comandi anche 
essi conformi alle ISO 7816-4. 
Ad un livello molto "superficiale", possiamo 
dire che solo l'amministratore di sistema della 
Smart Card è in grado di scrivere su di essa. 
Pertanto prima di poter accedere alla smart 
card in modalità amministrativa, sarà neces- 
sario autenticarsi. Appare ovvio che la Smart 
Card deve mantenere al suo interno, in un'a- 
rea protetta, la password dell'amministratore. 
Un client dall'esterno dovrà mandare al siste- 
ma operativo della Smart Card un "comando" 
che ha come parametro la password d'ammi- 
nistrazione. Il comando sarà uno di quelli 
esposti dal sistema operativo contenuto dalla 
Smart Card e sarà eseguito su di essa, verifi- 
cherà che la password inviata come parame- 
tro sia identica a quella contenuta nel file 
system e se l'autenticazione risulta corretta 
restituirà un Ok e garantirà l'accesso a livello 
amministrativo. Riassumendo, per poter scri- 
vere sulla Smart Card dovremo almeno com- 
piere le seguenti operazioni 

• Stabilire una connessione con la Smart 
Card 

• Inviargli il comando: "Autenticami con 
Password" 

• Aspettare il codice di ritorno 

Il comando viene inviato al sistema operativo 
tramite una periferica esterna, ma è sempre il 
sistema presente sulla Smart Card ad eseguir- 
lo. Un po' come succede tra la normale tastie- 
ra e il nostro computer. Il comando viene 
inviato dalla tastiera e dato in pasto al com- 
puter che lo esegue. Nel nostro caso, inviere- 
mo il comando da un software client presente 
sul computer, il lettore di Smart Card sarà la 
nostra interfaccia verso la Smart Card, il siste- 
ma operativo presente sulla Smart Card ese- 
guirà il comando. 



DISTRICARSI 

FRA LE SPECIFICHE 

Abbiamo già detto che il sistema operativo 
Sicrypt di Infineon è conforme agli standard 



ISO 7816-4 e PKCS #15 ma cosa vuol dire esat- 
tamente questo? Le IS07816 definiscono lo 
standard che deve essere adottato dalle Smart 
Card per poter essere compatibili con i lettori 
e con i software disponibili, descrive in 
sostanza: 1' Identification cards - Integrated 
circuits cards with contacts. Ovvero l'insieme 
delle parti elettriche, le strutture fisiche e 
logiche che devono essere rispettate dai pro- 
duttori di Smart Card. In particolare la strut- 
tura della IS07816 si compone di 10 parti: 

1. Caratteristiche fisiche 

2. Dimensioni e posizione dei contatti; 

3. Protocolli di trasmissione e segnali 
elettrici; 

4. Comandi, messaggi e risposte tra smart 
card e lettore; 

5. Regole di registrazione e identificazione 
delle applicazioni installate su Smart Card 

6. Regole e formati dei dati precostituiti su 
una Smart Card e di quelli scambiati con il 
lettore. 

7. Definisce la struttura logia di un DB per 
Smart Card e relativo SCQL, nonché i suoi 
comandi. 

8. Comandi e protocolli di sicurezza. 

9. Descrizione ciclo di vita di una smart card, 
dei suoi attributi di sicurezza. 

10. Definisce la modalità di RESET (Answer to 
Reset) e i segnali elettrici. 

Il sistema operativo Sicrypt è compatibile alla 
ISO 7816-4 ovvero alla quarta sezione delle 
specifiche in questione. Implementa cioè un 
set standard di comandi disponibili che resti- 





I TUOI APPUNTI 





1 




Applicazione 


1 


V 

Software Intierf. \ 
DBMS J 


1 




Sistema Operativo 


1 




r 






/ 




Dilver Lei loie 


l, 

■ Ltllùi e Sin art ■ 


^J 



Fig. 2: Architettura di un sistema di Smart Card 



http://www.ioprogrammo.it 



Settembre 2006/ 15 ► 



COVER STORY T I Gli standard e le tecniche per utilizzare le Smart Card 





ESEMPI 

E RIFERIMENTI 

Per gli esempi prodotti 

in questo articolo ci 

siamo avvalsi di alcuni 

progetti OpenSource 

facilmente reperibili 

all'indirizzo http://www. 

gotdotnetcom 

Le tecniche qui 

descritte si sono 

basate proprio sullo 

studio di questi 

esempi 



tuiscono messaggi anche essi aderenti allo 
standard. 

Le intere specifiche ISO 7816-4 sono acqui- 
stabili all'indirizzo http://www.iso.orq ad un 
costo di circa 120 . Per il nostro articolo, che 
ha scopo didattico e non necessita della cono- 
scenza delle intere ISO, ci siamo avvalsi di una 
pagina informativa relativa ai comandi espo- 
sti dal sistema Sycript disponibile all'indirizzo 
http://www.infineon.com/cqi- 
bin/ifx/portal/ep/channelView.do?channelld = - 
75271&channelPaqe=%2Fep%2Fchannel% 
2FproductCateqories.isp&paqeTvpeld=17224 



LO STANDARD PC/SC 

Nonostante che le ISO 7816 rappresentino la 
base per poter favorire l'interoperabilità tra le 
Smart Card, risultano troppo specifiche o 
troppo generiche in alcuni settori, per cui non 
sono state giudicate sufficienti a garantire la 
necessari uniformità fra le applicazioni. Per 
questo motivo nel 1996, Microsoft, Hewlett 
Packard, Shlumberger e Gemplus hanno dato 
vita a un gruppo di lavoro da cui è nato lo 
standard PC/SC. Tale sistema, non solo risol- 
ve il problema dell'interoperabilità tra smart 
card e lettore di diversa fabbricazione, ma fa 
si che lo sviluppatore si concentri sulla pro- 
grammazione e non sull'architettura di siste- 
ma. Per capire meglio la funzionalità dello 
standard PC/SC, diamo uno sguardo alla sua 



E'AEU" 



ICC (Integrateci Circuit Catti) Application 






] FI» Haliti 




IFDHmltr 




IFDHmlei 












PART 4 

































p 

A 
K 

T 




Fig. 3: Rappresentazione schematica dell'architettura PC/SC 



struttura. PC/SC prevede che il circuito inte- 
grato della Smart Card (ICC) debba aderire 
allTS07816 nelle parti 1-2-3-10 . Allo stesso 
modo il lettore di Smart Card (IFD) deve ade- 
rire all'IS07816 nelle stesse parti. E' anche 
utile sapere che una Smart Card al suo inter- 
no, ha una EEPROM con un livello logico 
strutturalmente analogo ad un File System di 
una memoria di massa generica; come lo è la 
sua unità di memoria lettura/ scrittura. In essa 
sono memorizzate alcune elaborazioni ese- 
guite dal processore, altre informazioni e pro- 
grammi aggiuntivi (ad esempio le Applet) che 
arricchiscono le peculiarità predefinite di 
base della carta. Tanto per farla breve e non 
entrare in specifiche tecniche eccessivamente 
complesse diremo che PC/SC prevede tre 
metodi di accesso alle Smart Card 

• Win 32: Tramite interfacce API di basso 
livello, che lasciano una grande libertà al 
programmatore ma necessitano della 
conoscenza approfondita di buona parte 
del sistema operativo presenta sulla Smart 
Card e degli altri dettagli tecnici 

• CryptoAPI: Tramite interfacce API 
Crittografiche. Queste API implementano 
un alto livello per la crittografia delle infor- 
mazioni, ma dipendono in modo molto 
forte da una particolare architettura e dalla 
tipologia di lettore /smart card. 
Attualmente in Windows le Cripto Api sono 
disponibili per alcuni modelli di Smart 
Card prodotti da Gemplus e da 
Schlumberger 

• Scard COM: Si tratta di un'interfaccia non 
crittografica, di alto livello che "preleva" 
dalla Smart Card alcuni servizi e li rende 
disponibili al client 

Per il nostro articolo utilizzeremo il primo 
metodo, che ci garantisce un'alta flessibilità 
ed è sufficientemente documentato in 
Windows. 



IL PLATFORM INVOKE 

Le API Win32 rese disponibili da Windows 
sono contenute nella DLL winscard.dll. Chi 
segue ioProgrammo da un po' di tempo sa già 
che è possibile invocare una DLL unmanaged 
dall'interno del .NET framework con una tec- 
nologia nota come Platform Invoke. Un esem- 
pio generico di Platform Invoke è il seguente: 



► 16 /Settembre 2006 



http://www.ioprogrammo.it 



Gli standard e le tecniche per utilizzare le Smart Card ■ ▼ COVER STORY 



Imports System 



Imports Sy sterri. Runti me. InteropServices 



<DIIImport("libreria.dN", 

EntryPoint: 



"nomeFunzione", 



SetLastError:=True, ExactSpelling:=True, _ 
CallingConvention:=CallingConvention.StdCall)> _ 
Public Function nomeFunzione(parametri, ecc .. 

parametro ) 

End Function 

Per quanto riguarda in particolare la win- 
scard.dll potremo utilizzare qualcosa del 
genere: 

[DIIImport("WinScard.dll")] 

public static extern int SCardEstablishContext(int 
dwScope, int nNotUsedl,int nNotUsed2, ref int 

phContext); 

Impareremo il significato delle varie funzioni 
esposte dalla DLL in questione man mano che 
andremo avanti nella comprensione della tee- 



ALLA SMART CARD 

Prima di tutto cerchiamo di capire quali sono 
i passi logici che andremo ad effettuare. 
Potremo riepilogare il flusso delle operazioni 
come segue: 

1) Stabilire il contesto del "resource manager". 
Il resource manager si occupa di gestire 
l'accesso alle risorse collegate al computer. 
E' sostanzialmente una sorta di motore a 
cui fare riferimento per ottenere l'accesso 
ad eventuali lettori collegati. Stabilirne il 
contesto significa ottenere un riferimento 
da poter utilizzare per poterlo invocare. Ad 
esempio sarà il resource manager che ci 
indicherà se ci sono lettori connessi, quan- 
ti sono, e qual è il loro stato. Ogni volta che 
invochiamo un metodo della winscard.dll, 
dovremo passargli il riferimento del 
resource manager, di modo che il metodo 
in questione sappia a chi si deve rivolgere 
per ottenere le informazioni che gli servo- 
no. Un esempio in C# di come ottenere il 
resource manager è il seguente: 



private 


void 


Forml_ 


_Load(object 
sender, System 


EventArgs 


e) 


{ 


uint nContext = 2; 




int 


nNotUsedl = 0; 









int nNotUsed2 = 0; 


this. nContext = 0; 


string error = ""; 


int nRetVall = 
SCardEstablishContext( nContext, 
nNotUsed2, ref this 


nNotUsedl, 
.nContext); 


if (nRetVall != 0) 


{ 


error = "error"; 


} 



Cerchiamo anche di capire quali sono i para- 
metri passati alla SCardEstablishContextfJ. 
In particolare l'nContext rappresenta lo 
"scope" dell'applicazione e può valere 

SCARD_SCOPE_ USER 
SCARD_SCOPE_SYSTEM 

Nel primo caso il resource manager potrà 
essere usato a livello di utente, nel secondo 
caso a livello di sistema. In questo secondo 
caso l'applicazione dovrà avere i permessi 
corretti. I parametri "nNotUsedl e 
nNotUsed2, non sono attualmente imple- 
mentati, servono per sviluppi futuri e nel 
nostro caso devono essere dunque settati a 
o a nuli. Infine nContext conterrà l'handle 
generato come riferimento al resource mana- 
ger e che come vedete abbiamo settato come 
globale all'applicazione, perché lo utilizzere- 
mo come parametro per tutte le funzioni che 
utilizzeremo in futuro. Se la connessione al 
resource manager ha esito positivo otterremo 
un messaggio di SCARD_S_SUCCESS. Se falli- 
sce otterremo un errore specifico. Un elenco è 
disponibile al seguente indirizzo: http:// 
msdn.microsoft.com/librarv/en-us/secauthn/secu - 
ritv/authentication return values.asp?FRAIVIE=tr 
ue#smart card return values 

2) Ottenere l'elenco dei lettori collegati al 
sistema. La funzione da utilizzare è la 
SCardListReader. E' possibile richiamarla 
con il platform invoke tramite il seguente 
codice: 

public static extern int SCardListReaders 

(int hContext, string cGroups,ref string 
cReaderLists, ref int nReaderCount); 
int nRetVal2 = 
SCardListReaderGroups(this. nContext, 

ref cGroupList, ref nStringSize); 
if (nRetVal2 != 0) 

{ 

error = "error"; 




http://www.ioprogrammo.it 



Settembre 2006/ 17 ► 



COVER STORY T 



Gli standard e le tecniche per utilizzare le Smart Card 




string[] cGroups = cGroupList.Split(delimiter); 
string cReaderList = "" + Convert.ToChar(O); 
int nReaderCount = -1; 
int nRetVal4 = SCardListReaders(this.nContext, 
cGroups[0], ref cReaderList, ref nReaderCount); 
if (nRetVal4 != 0) 
{ 



} 

if (error 



"") { 



string[] cReaders = 

cReaderList. Spi it(delim iter); 
toolStripStatusLabell.Text = 



cReaders[0]; 



this.readername = cReaders[0]; 



connect(); 



verifypin(); 



} else { 



if (MessageBox.Show("Errore di 
comunicazione lettore non presente " , "Error", 
MessageBoxButtons.OK, 
MessageBoxIcon.Question) == DialogResult.OK) 




{ 



FUNZIONE DISPLAYSCERROR 



E' semplicemente una funzione 
di servizio che utilizziamo per 
mostrare un messaggio 
comprensibile, in seguito al 
verificarsi di una condizione 
d'errorre. Un estratto della 
funzione in questione è la 
seguente: 

private void DisplaySCError 

(int nErrCode, string cText) 



cErrString = "Internai 
Error"; 



break; 



case "0x80100002" 



cErrString 



"Cancelled"; 



break; 



[...] 



{ 






string cErrString = 


_ un. 


Stri 


ng 


string ErrCode = 
Format("0x{0:X}", 


nErrCode); 




switch (ErrCode) 


{ 



if (MessageBox.Show("Errore di 
comunicazione "+ cErrString, "Error", 
MessageBoxButtons.OK, 
MessageBoxIcon.Question) = = 
DialogResult.OK) 

{ 

Application. Exit(); 



case "0x80100001" 



Application. Exit(); 



} 



Come potete anche vedere, abbiamo creato 
una funzione apposita per ricavare la stringa 
corretta dove saranno contenuti i nomi dei 
lettori. Anche in questo caso notate che 
abbiamo passato come parametro il contesto 
del resource manager. 
Notate anche che nell'esempio in C# abbiamo 



associato this.readername = cReaders [0]; e 
subito dopo abbiamo richiamato connect() e 
verifypin(). Queste due funzioni vengono 
richiamate se esiste almeno un lettore presen- 
te collegato al PC. 

3) Connettersi alla smart card: in questo caso- 
la funzione da invocare è la SCardConnect. 
Via Platform Invoke si tratterà di utilizzarla 
come segue: 

public static extern int SCardConnect 

(int hContext, string cReaderName, 

uint dwShareMode, uint dwPrefProtocol, ref int 

phCard, ref int ActiveProtocol); 



Il nostro esempio in C# 


è il seguente: 


private void connect(){ 


uint nSh 


areMode 


= 1; 


uint nPrefProtocol 


= 2; 




this.nCard = 0; 



this.nActiveProtocol = 0; 
int nRetVal6 = 
SCardConnect(this.nContext, this.readername, 
nShareMode, nPrefProtocol, ref this.nCard, ref 
this.nActiveProtocol); 
if (nRetVal6 != 0) 

DisplaySCError(nRetVal6, 

"SCardConnect()"); 
} 

Notate che la SCardConnect prende come 
parametri il contesto del resource manager, il 
nome del lettore , il protocollo da usare per la 
trasmissione. In questo caso è stato scelto il 
trasferimento T0 che non specifica il proto- 
collo utilizzato. Potevano essere specificati o il 
protocollo RAW o TI mediante le costanti 
SCARD_PROTOCOL_T0 o SCARD_PROTO- 
COL_Ti ma questo lo lasciamo a voi perché 
dipende dal tipo di lettore usato. 



VERIFICHIAMO IL PINI 

Per poter verificare il PIN , dobbiamo inviare 
alla card un comando ADPU. I Comandi 
ADPU rispondono allo standard IS07816-4, 
tuttavia è sempre opportuno consultare la 
documentazione relativa al sistema operativo 
presente sulla Smart Card. Nel caso di infi- 
neon un breve estratto dei comandi più 
importanti è presente all'URL http://www. infi - 
neon.com/cqi-bin/ifx/portal/ep/channel 
View,do?channelld = -75271&channel 
Paqe=%2Fep%2Fchannel%2FproductCateqories.i 
sp&paqeTvpeld=1 7224 



► 18 /Settembre 2006 



http://www.ioprogrammo.it 



Gli standard e le tecniche per utilizzare le Smart Card ■ ▼ COVER STORY 



Curiosando nella documentazione scopriamo 
che il comando per verificare la password di 
Amministratore della scheda è il seguente 

00 20 00 02 08 31 32 33 34 35 36 37 38 

E se non si verifica nessun errore il codice di 
risposta della scheda deve essere 

90 00 

Dove i numeri da 31 in poi rappresentano il 
PIN da passare alla scheda. Nel nostro caso 
12345678. Per mandare un ADPU al sistema 
operativo è necessario utilizzare la funzione 
ScardTransmit. Il cui prototipo è definito 
come segue 

[DIIImport("WinScard.dll")] 

public static extern int SCardTransmit(int 
hCard, ref SCARD_IO„REQUEST pioSendPci, 

byte[] 

pbSendBuffer, int cbSendLength, ref 

SCARD_IO_REQUEST pioRecvPci, ref byte 

pbRecvBuffer, ref int pcbRecvLength); 



ILenln = 17 



ILenOut = 2 



IRet = SCardTransmit(hCard, ioInPci, APDU(0), 

ILenln, ioInPci, ucBufOut(O), ILenOut) 

Nel codice che abbiamo visto sopra, abbiamo 
creato una funzione che inserisce in un array 
di bytes, la stringa contenuta tra apici. 
Questo vi faciliterà il compito quando dovrete 
scrivere dati prettamente alfanumerici. 
Effettuata la scrittura del codice, come sem- 
pre controlleremo l'esito della risposta e suc- 
cessivamente, ci disconnetteremo dalla Smart 
Card con il metodo SCardDisconnect inter- 
rompendo l'alimentazione della carta: 

If (bBufOut(LenOut - 2) <> &H90S) And 

(bBufOut(LenOut - 1) <> &H0S) Then 
ListBoxl.Items.Add("Scrittura dati nella Smart 

Card fallita") 
ListBoxl.Items.Add("Numero errore: " & result) 
Exit Sub 
End If 
result = SCardDisconnect(hCard, 

SCARD_UNPOWER_CARD) 




Per brevità non trascriviamo l'intero codice 
per inviare l'ADPU, potete comunque trovare 
un riferimento nel codice allegato all'articolo. 
Quel che più conta è che sia chiaro quali sono 
i passi logici da compiere per arrivare a questo 
punto 



LEGGIAMO 

IL CODICE SEGRETO 

Adesso non ci resta che mostrare come legge- 
re il codice che abbiamo scritto in preceden- 



SCRIVERE 

UHI PROPRIO CODICE 

Una volta che siamo autenticati con la pas- 
sword di amministratore, possiamo scrivere 
un nostro PIN utente nella scheda. Per farlo 
possiamo usare qualcosa del genere. 
L'esempio questa volta è in Visual Basic.NET 



APDU(0) 


= &H0S 


APDU(l) 


= &HD6S 'comando di scrittura UPDATE 

BINARY 


APDU(2) 


= &H0S 


APDU(3) 


= &H20S 'indirizzo della scrittura 



APDU(4) = &HBS 

'numero di bytes da scrivere B = 

'11 in HEX che sarebbe "IoProgrammo" 

'Imposto la lunghezza della stringa 

'da scrivere nella SmartCard 

lenCode = 11 



' adesso costruisco la 


stringa da 


inserire 


nella 


se 


InsStr2ArrByte 


(APDU, 


5, 


"IoProg 


rammo' 


) 






'lunghezza dei 


dati de 


Ila 


APDUa 









(CLA 


INS 


P1 


P2 


LC 


DATA 


LE ] 


lo 


B0 





20 


05 





0B I 





za. Per far questo la procedura è molto simile 
alla scrittura. Se la connessione è andata a 
buon fine, dobbiamo occuparci della costru- 
zione della APDU. La differenza sta nell'utiliz- 
zare il comando READ BINARY invece del 
UPDATE BINARY. Il READ BINARY è definito 
come segue: Il confronto dei dati avverrà poi 
nel vostro programma, comparando sempli- 
cemente le stringhe. 
Analizziamo il codice: 

'Il comando seguente è un comando di lettura. 

'Legge 5 byte a partire dall'indirizzo &H20 

bAPDU(O) = &H0S 'da 

bAPDU(l) = &HB0S 'iris (Instruction) 

'(B0 determina il comando di lettura) 

bAPDU(2) = &H0S 'PI. byte alto 

'dell'indirizzo di lettura/scrittura 

bAPDU(3) = &H20S 

'P2. byte basso dell'indirizzo di lettura/scrittura 



http://www.ioprogrammo.it 



Settembre 2006/ 19 ». 



COVER STORY T 



Gli standard e le tecniche per utilizzare le Smart Card 




bAPDU(4) = &HBS 

'LE (lunghezza in byte da leggere) quindi B in 
'esadecimale = 11 per IoProgrammo 
'parametro LC che definisce 
'la lunghezza dei byte inviati 
Lenin = 5 

'lunghezza dei byte ricevuti 
'dalla funzione + 2 byte di risposta 
'(SW1 e SW2) 
LenOut = bAPDU(4) + 2 

result = SCardTransmit(hCard, ioInPci, bAPDU(O), 
Lenin, ioInPci, bBufOut(O), LenOut) 

Una volta impostata l'APDU, ne constatiamo 
l'esito positivo. Anche qui come campi SW1 e 
SW2, dobbiamo aspettarci rispettivamente i 
valori 0x90 0x00. In caso non fossero tali, vor- 
rebbe dire che il comando non è andato a 
buon fine. 



alcun SDK. C'è da dire che ce ne sono molti in 
commercio e tutti ben fatti. Il problema prin- 
cipale è il loro costo. Quelli che vi possiamo 
consigliare, a basso costo ma con funziona- 
lità davvero elevate, sono quello creato dalla 
Subsembly. Si integra benissimo con il siste- 
ma operativo e con l'ambiente di program- 
mazione .NET e anche su sistemi operativi 
Windows CE. La miglior soluzione per rap- 
porto prezzo-prestazioni. Uno che mi sento 
di consigliare, è senza alcun dubbio 
l'ASECard Memory Smart Card SDK venduto 
dalla ATHENA che comprende un lettore, le 
smart card e l'sdk per il loro sviluppo. 
Il loro costo si basa sul tipo di SDK e sul tipo 
di smart card. Il kit è possibile acquistarlo 
anche presso la PartnerData s.r.l. 
Oppure non spendere nulla e scegliere quello 
gratuito Microsoft. 



'Controllo se i valori della risposta sono &h90 e 
&H00 che contrassegnano la riuscita del comando 
If (bBufOut(LenOut - 2) <> &H90S) And 

(bBufOut(LenOut - 1) <> &H0S) Then 
ListBoxl.Items.Add 

("Lettura dati non riuscita!") 
Else 



Se il tutto è OK, il codice è stato letto corret- 
tamente. 

SDK E PACCHETTI 
DI TERZE PARTI 

Abbiamo imparato i passi fondamentali da 
compiere per poter creare un semplice siste- 
ma di protezione, utilizzando le librerie for- 
nite dal sistema operativo e senza acquistare 



PIH 



Fila (MF) ■ 3FDD 

Dedicitri File «FI - 3IDD/DatiLicenia 



_V| Elimini»-» File (EFI- 3131 



Eliminar» Fili 1EF] ■ 313! 



^ 



Ocdoted File (DFI - 32C0 



(P.MEFI 3Z31 



PIN 



-Ins ^ r VPtQ9rspNic Keys - ID 

"jì USER HH - DI 

J MMIMSIFMDN PIN - C2 

Gerarchia del File System di una EEPROM 



Fig. 4: Il file system contenuto nella Smart Cards 



CONCLUSIONI 

Nella programmazione di applicazioni che 
fanno uso delle smart card, il problema prin- 
cipale resta legato ai diversi hardware e siste- 
mi operativi supportati dalle schede. 
Nonostante si sia fatto un grande sforzo per 
ottenere degli standard affidabili, tuttavia 
nella pratica si riscontrano seri problemi nel 
far funzionare le applicazioni con ogni tipo di 
dispositivo e con ogni tipo di scheda. 
In fase di produzione possiamo consigliarvi 
di testare il software sempre con lettori e 
schede specifiche e di rilasciarlo solo come 
conforme a quel particolare tipo di dispositi- 
vo. Il ciclo di programmazione risulta poi 
abbastanza semplice se si usa la winscard.dll. 
L-importante è avere capito quali sono i passi 
necessari per poter accedere in lettura/scrit- 
tura alla Smart Card. 

La sintassi e la semantica delle funzioni espo- 
ste dalla winscard.dll è facilmente reperibile 
nella documentazione ufficuale Microsoft su 
http://msdn.microsoft.com 

Abbiamo analizzato diverse problematiche 
relative alla protezione di un semplice 
software mediante una Smart Card. 
Grazie al percorso intrapreso in questo arti- 
colo, sarete in grado di proteggere ogni tipo 
di software utilizzando il sistema descritto. 
Se avete poi possibilità di spendere qualche 
soldo in più, abbiamo elencato due degli SDK 
più produttivi in circolazione. 
Lasciamo a voi lettori il piacere di approfon- 
dire i temi trattati e di lasciar essere traspor- 
tati dalla curiosità, grande stimolo per noi 
programmatori. 



► 20 /Settembre 2006 



http://www.ioprogrammo.it 



ioProgrammo Web T I Programma in XML ottieni FLASH 



DA XML A FLASH 
PASSANDO PER FLEX 

UNA GUIDA PASSO PASSO ALLA NUOVA VERSIONE DEL PRODOTTO DI ADOBE DEDICATO AGLI 
SVILUPPATORI. VEDREMO COME, IN MODO RAPIDO E VISUALE, SI POSSANO SVILUPPARE 
INTERFACCE CHE FUNZIONANO SIA PER IL WEB SIA STANDALONE E PER TUTTE LE PIATTAFORME 




Una volta c'erano i compilatori! Ovvero 
un tizio crea un file di testo con dentro 
delle istruzioni ben precise, lo dà in 
pasto ad un certo programma e quello ne tira 
fuori un eseguibile. È il principio base della pro- 
grammazione. Tanto per capirci facciamo un 
esempio banale. Supponiamo di avere scritto 
con il notepad un fantastico file di testo conte- 
nente la seguente roba e di avere salvato questo 
file con il nome "pluto.mxml" 



apprendimento veramente bassa. I costi? Nulli! 
Il compilatore è assolutamente gratuito e libera- 
mente scaricabile dal sito di Adobe. Se non vole- 
te spendere neanche i soldi della connessione 
ad Internet, lo trovate allegato nel CD di 
ioProgrammo. Se invece volete qualche como- 
dità aggiuntiva, dovrete metter mano al portafo- 
glio. Ma di questo parleremo meglio nel Box 
relativo a Flex Builder 



n 




REQUISITI 



,— Basi di XML, 
I ActionScript, FLASH 



Flex SDK, Flex Builder, 
Eclipse 



^E^^ [ 



Tempo di realizzazione 



<mx:Button x="54" y="71" label = "Button2" 

click="clickHandler(event)"/> 

Ora, supponiamo che sulla nostra macchina sia 
presente un compilatore che si chiama mxmlc. 
Potrei provare a dargli in pasto il mio file come 
segue: 

mxmlc — strict=true — file-specs pluto.mxml 

Ovviamente, quel che fa il compilatore è affare 
del compilatore! Potrebbe generare un eseguibi- 
le, un file HTML, un file in formato flash o java! 
Nello specifico Flex 2.0 è un compilatore. Prende 
in pasto un file XML creato con una certa sintas- 
si e genera in output un file in formato Flash 
SWF. La cosa stuzzicante è che il file XML che 
diamo in pasto al compilatore può contenere 
oggetti quali bottoni, combobox, checkbox, fun- 
zioni, e handler di eventi. Capirete che la solu- 
zione è molto interessante e per svariati motivi 

1) È possibile generare applicazioni Flash che 
girano esattamente allo stesso modo sia sul 
Web che in modo Standalone 

2) Le applicazioni Flash girano esattamente in 
modo identico sia su Linux che su Windows 

3) Il formato flash consente di creare layout 
spettacolari 

In buona sostanza è tutto quello che fa Java 
unito però alla semplicità e la potenza di un lin- 
guaggio che come vedremo ha una curva di 



IL PRIMO VAGITO 

Iniziamo con creare un file chiamato con grande 
fantasia helloworld.mxml. Come già detto pote- 
te tranquillamente usare il notepad. 
Riempiamolo con qualcosa del genere: 

<?xml version = "1.0" encoding = "utf-8"?> 
<mx:Application 

xml ns:mx=" http://www.adobe.com/2006/mxml" 
layout="absolute"> 
<mx:Label x="177" y="172" 
text="Hello World" 
id = "labell" 
width = "113" 
fontSize="19" 
fontFamily="Arial" 
color="#ffffff" 
fontWeight="bold"/> 
</mx: Application > 

Diamolo in pasto al compilatore come abbiamo 
già fatto all'inizio dell'articolo, nel modo 
seguente 

mxmlc — strict=true —file-specs helloworld.mxml 

Otterremo il file helloword.swf, cliccando sul 
quale vedremo nel player flash una finestra gri- 
gia al cui centro campeggerà la magica scritta 
"Hello World". Ovviamente possiamo anche pro- 
vare a includere la nostra applicazione in un file 
html per renderla disponibile sul web, come 



► 22 /Settembre 2006 



http://www.ioprogrammo.it 



Programma in XML ottieni FLASH ■ T ioProgrammo Web 



riportato nel seguente spezzone di codice 

<noscript> 

<object classid = "clsid:D27CDB6E-AE6D- 

llcf-96B8-444553540000" 
id = "pippo" 

width = "100%" height="100%" 
codebase="http://fpdownload 
.macromedia.com/get/flashplayer 
/current/swflash.cab"> 
<param name="movie" 

value="pippo.swf" /> 
<param name="quality" 

value="high" /> 
<param name="bgcolor" 

value="#869ca7" /> 
<param name="allowScriptAccess" 
value="sameDomain" /> 
<embed src="pippo.swf" quality="high" 
bgcolor="#869ca7" width = "100%" height="100%" 
name="pippo" align = "middle" play="true" 
loop = "false" quality="high" 
allowScriptAccess="sameDomain" 
type="application/x-shockwave-flash" 
pluginspage= "http://www.adobe.com/go/ 
getflashplayer"> 
</embed> 
</object> 
</noscript> 

Non è questo l'articolo che illustra come inserire 
una qualunque applicazione flash in un file 
HTML, tuttavia la tecnica da eseguire è esatta- 
mente quella classica. 



CHE CE IM QUEL 

Le prime due righe sono composte come segue: 

<?xml version = "1.0" encoding = "utf-8"?> 
<mx:Application 

xmlns:mx= "http://www.adobe.com/2006/mxml" 
layout="absolute"> 

Ovvero indichiamo che si tratta di un file in for- 
mato XML, instanziamo il primo "Container" 
ovvero l'applicazione. L'applicazione è il conte- 
nitore madre di tutti gli altri. Identificatelo se 
volete con la form. L'attributo layout=absolute 
ha più o meno lo stesso significato tipico dei 
layout di java. Ovvero indica l'allineamento che 
gli oggetti container devono seguire. Nel nostro 
caso abbiamo specificato che siamo noi a indi- 
care la posizione in coordinate cartesiane dei 
vari oggetti che vogliamo disporre sulla form. 
Il prossimo oggetto è più interessante. Si tratta di 
una label che abbiamo posizionato sulla form e 



identifichiamo con il nome labell 

<mx:Label x="177" y="172" 
text="Hello World" 
id = "labell" 

omettiamo di parlare degli altri attributi per bre- 
vità e perché il loro significato ci pare piuttosto 
evidente. 



GIOCHIAMO UHI PO' 

Quello che faremo adesso è aggiungere un bot- 
tone all'applicazione, premendo il quale la 
nostra label cambierà in "Siamo tutti amici di 
ioProgrammo". Il nostro codice varia come 
segue: 

<mx:Application 

xml ns:mx=" http://www.adobe.com/2006/mxml" 
layout="absolute"> 
<mx: Label text="Hello World" 
id = "labell" 

width = "113" fontSize="19" 
fontFamily="Arial" 
color="#ffffff" 
fontWeight="bold" 
x="177" y="127" 

/> 

<mx:Button label = "Button" 
x="201" y="194" 
id = "buttonl" 
click= "label l.text=" 

Siamo tutti amici di ioProgrammo 
"" 

/> 

</mx: Application > 

Come vedete il codice è abbastanza semplice, 
non abbiamo fatto nient' altro che cambiare la 
property text della label utilizzando l'evento 
click sul bottone. Semplice, ma il codice è un po' 
sporco. Rendiamolo più elegante utilizzando 
una function e un gestore dell'evento clic. 
Quello che vedrete di seguito sicuramente susci- 
terà un sorriso nei programmatori, perché 
lascerà intravedere tutte le infinite possibilità di 





A ABBIAMO BISOGNO. 



Prima di tutto del compilatore. Lo 
trovate all'indirizzo 

https://www.adobe.com/cfusion/tdrc/ind 
ex.cfm?product=flex. Troverete sia la 
versione per Windows che la 
versione per Linux. In tutti e due i 



casi il prodotto è gratuito. Una 
volta terminata l'installazione 
avrete a disposizione fra le altre 
cose il magico "mxml" ovvero il 
compilatore che useremo per gli 
esempi di questo articolo 



http://www.ioprogrammo.it 



Settembre 2006/ 23 ► 



ioProgrammo Web T I Programma in XML ottieni FLASH 




questo strumento, il codice è il seguente: 

<mx:Button label = "Button" 

x = "201" y="194" id = "buttonl" 
click="clickHandler(event)" 

_l> 

<mx:Script> 

<![CDATA[ 

import flash. events.MouseEvent; 
private function clickHandler ( 

event:MouseEvent ):voìd 



{ 



]]> 



labell.text = "Siamo tutti amici di 

ioProgrammo"; 



</mx:Script> 



</mx:Application> 

Molto semplicemente intercettiamo l'evento 
Click sul bottone e in relazione a questo faccia- 
mo partire una funzione che prende come para- 
metro l'evento stesso. La funzione non fa altro 
che modificare la property text della label. Quasi 
tutto quello di cui noi programmatori abbiamo 
bisogno è qui! Chi è abituato a programmare 
con un qualunque linguaggio non può non 
avere già familiarizzato con questi concetti. La 
curva di apprendimento di questo linguaggio è 
praticamente nulla! 



width = "407" 

fontSize="19" fontFamily="Arial" 
color="#ffffff" fontWeight="bold" 
textAlign = "center" 
horizontalCenter="-6" verticalCenter= 



'-38" 



/> 



<mx:Script source="script.as" /> 



<mx:ComboBox id = "combolist" 

change="cambiaStringa()" 
horizontalCenter="0" 
verticalCenter="6"> 
<mx:Array> 



<mx:Object data = "0" label = 


"Bello" /> 


<mx:Object data = "l" label = 


"Brutto" /> 


<mx:Object data = "2" label = 


"Completo"/> 


<mx:Object data = "3" label = 


"Grandioso"/> 


<mx:Object data = "4" label = 


"Meraviglioso" /> 


</mx:Array> 


</mx:ComboBox> 


Vi invito a fare attenzione alla 


seguente riga: 


<mx:Script source="script.as" /> 



Molto semplicemente in questo modo si indica 
che ingloberemo nel nostro file msxml le fun- 
zioni, le classi, le interfacce descritte con in lin- 
guaggio ActionScript all'interno del file script, 
as. Nel nostro esempio il codice all'interno del 
file in questione sarà 



function cambiaStringa(){ 




COMPLICHIAMOCI 
UHI PO' LA VITA 

Quella che costruiremo adesso è un'applicazio- 
ne banale, ma ci dà la possibilità di introdurre 
ancora qualche concetto su Flex. La nostra form 
adesso si comporrà di una stringa e di una com- 
bobox. Quando l'utente selezionerà un elemen- 
to della combobox la stringa varierà di conse- 
guenza. Il codice mxml è il seguente: 

<mx:Label text="Hello World" 
id = "labell" 



EX BUILDER 



Adobe mette a disposizione un 
Plughi di Eclipse piuttosto 
potente che consente di 
sviluppare applicazioni Flex in 
modo rapido e visuale. Non solo 
il plugin è dota eclipse di 
Syntax Highlighting e Code 
Complexion per le applicazioni 
Flex, ma anche di un comodo 
Designer che fa si che le 



interfacce possano essere 
sviluppate in modo del tutto 
RAD. Flex Builder consente 
anche di compilare al volo le 
applicazioni ed è dotato di tutta 
una serie di Add-On che 
rendono davvero immediato lo 
sviluppo con Flex. Il prodotto 
non è gratuito ed è acquistabile 
al prezzo di 538 



J 



var stringa = combolist.selectedLabel; 
labell.text="ioProgrammo è "+stringa; 



La funzione cambiaStringaO verrà eseguita 
quando verrà intercettato l'evento change sulla 
combobox, grazie alla seguente linea 

<mx:ComboBox id = "combolist" 

change= "cambiaStringaO" 

horizontalCenter="0" 

verticalCenter="6" 



Ora, l'esempio è sicuramente banale. Ma i più 
attenti avranno intuito quali sono i vantaggi di 
un approccio del genere. 

• Separazione della logica di business da quel- 
la di presentazione 

• Disponibilità di un linguaggio ad oggetti di 
alto livello 

Le possibilità a questo punto diventano infi- 
nite. Per completezza riportiamo un esempio 
con qualche costrutto più complesso. Questa 



► 24 /Settembre 2006 



http://www.ioprogrammo.it 



Programma in XML ottieni FLASH ■ T ioProgrammo Web 



volta avremo una forni che propone una 
domanda. Una listbox contenente tre rispo- 
ste e infine un bottone. L'utente dovrà sele- 
zionare la risposta corretta dalla listbox e 
l'applicazione dovrà mostrare un messaggio 
che indica "hai vinto" se la risposta è corretta 
e "hai perso" se la risposta è errata. Vediamo 
il codice: 



<mx:Lìst id = "miaList" horizo 


ntalCenter="0" 
verticalCenter="5"> 


<mx:dataProvider> 


<mx:Object data = 


'0" 


label = "Paolino"/> 


<mx:Object data = 


'1" 


label = "Panino" /> 


<mx:Object data = 


'1" 


label = "Poldino"/> 


<mx:Object data = 


'1" 


label = "Paperello"/> 


<mx:Object data = 


'1" 


label = "PincoPallo" /> 


</mx:dataProvider> 


</mx:List> 



:Button click="controllarisposta()" 
label = "Button" 
horizontalCenter="0" 
verticalCenter="138" 



/> 



<mx:Label 



text="Qual è il cognome di Paperino?" 
width="417" horizontalCenter="-2" 
verticalCenter="-113" textAlign = "center" 
id = "labell" 



/> 



E naturalmente il codice della funzione con- 
trollarispostaQ contenuta in script.as 



function control 


arisposta():Boolean { 






var answer=mial_ist.se 


lectedlte 


n.data; 


if (answer==0) { 






labell.text= 


'Risposta 


Esatta"; 




} else 


{ 










labell.text= 


'Risposta 


Errata"; 


} 




return 


true; 






} 



Come vedete si tratta di un esempio decisa- 
mente semplice, tuttavia ci serve per capire 
quale sia l'interazione fra ActionScript e 
msxml. 

Se avete fatto attenzione, avrete anche notato 
che il codice che abbiamo fin qui usato nello 
script.as è esattamente dello stesso tipo che 
nel primo esempio abbiamo usato inLine. 
ActionScript è il linguaggio di alto livello che 
ci consente di interagire con gli oggetti espo- 
sti da msxml. 

L'esempio qui proposto ci dà anche la possi- 
bilità di introdurre un nuovo concetto: quello 
di dataprovider. 



INTERAGIRE CON I DATI 

Fin qui avrete notato che i dati sono stati inseri- 
ti negli script in modo statico. Sia nel caso della 
combobox che nel caso della listbox, abbiamo 
scritto i dati direttamente nel codice. 
Ovviamente questa non è una grande idea! 
Tipicamente i dati sono contenuti in un databa- 
se. Deve esistere in flex un modo per interagire 
con i database. Ed in effetti esiste!. 
Per questo primo esempio i nostri dati saranno 
contenuti in un file XML. Vedremo in seguito a 
quali altri tipi di database possiamo accedere 
con Flex. Considerate per ora le seguenti linee 
di codice: 

<?xml version = "1.0" encoding = "utf-8"?> 
<mx:Applìcation 

xmlns:mx= "http://www.adobe.com/2006/mxml" 
layout ="absolute"> 
<mx:Script source="script.as" /> 
<mx:Model id = "q" source="risposte.xml" /> 



<mx:List id = 



"miaList" 
labelField = "label" 
horizontalCenter="0" 
verticalCenter="5" 
dataProvider="{q.q}" 



/> 



<mx:Button click="controllarisposta()" 
label = "Button" 
horizontalCenter="0" 
verticalCenter="138" 

_/> 

<mx:Label 

text="Qual è il cognome di Paperino?" 
width = "417" horizontalCenter="-2" 
verticalCenter="-113" 
textAlig n = "center" 
id = "labell"/> 



</mx:Application> 



Con il relativo file XML 



<?xml version 


= "1.0" encoding = "iso-8859-l"?> 


<questions> 


<q label = 


'Paolino" data = "0"/> 


<q label = 


'Panino" data = "l"/> 


<q label = 


'Poldino" data = "l"/> 


<q label = 


'Paperello" data = "l"/> 


<q label = 


'Pincopallo" data = "l"/> 


</questions> 



Utilizzando questa tecnica abbiamo stabilito 
una sorta di relazione stretta tra l'oggetto List e 
il file risposte.xml. Tutta la logica di "Binding" è 
contenuta in queste linee 

<mx:Model id = "q" source="risposte.xml" /> 
<mx:List id = "miaList" labelField = "label" 




http://www.ioprogrammo.it 



Settembre 2006/ 25 ► 



ioProgrammo Web T I Programma in XML ottieni FLASH 





horizontalCenter="0" verticalCenter="5" 
dataProvider="{q.q}"/> 

Non ci soffermeremo in questo articolo sulla 
logica che sottende al databinding e su qual è la 
sintassi di questi metodi. Quello che più impor- 
ta in questo momento è sapere che esiste la pos- 
sibilità di utilizzare un DataProvider per recupe- 
rare i dati. L'esempio che abbiamo proposto per 
XML è significativo. Nelle prossime puntate di 
ioProgrammo avremo modo di soffermarci ulte- 
riormente sull'argomento. 



FLEX E GLI ALTRI 

Fra le possibilità più interessanti offerte da Flex 
c'è quella di poter interagire con altri linguaggi. 
Iniziamo con qualche esempio di interazione 
con PHP. Consideriamo il seguente script PHP 

$mysql = mysql_connect(DATABASE_SERVER, 

DATABASEJJSERNAME, 
DATABASE_PASSWORD); 

mysql_select_db( DATABASE_NAME ); 

$Query = "SELECT * from redazione"; 

$Result = mysql_query( $Query ); 

$Return = "<redattori>"; 

while ( $User = mysql_fetch_object( $Result ) ) 

{ 

$Return .= "<redattore> 

<nome>" .$User->Nome."</nome> 
<cognome>".$User->Cognome."</cognome> 
</redattore>"; 

} 

$Return .= "</redattori>"; 
mysql_free_result( $Result ); 
print ($Return) 
?> 



Non fa altro che connettersi ad un database, 
recuperare un elenco di utenti e stampare il 
risultato formattandolo come un file XML nella 
forma: 



<redattori> 



LA SICUREZZA? 



Per consentire ad un'applicazione 
Flex/Flash di richiamare un file 
presente su un web server 
esterno alla macchina su cui 
risiede l'applicazione, è 
necessario inserire nella root del 
web server un file 
crossdomain.xml che deve 
contenere le policy di permesso 
per le applicazioni flash. Un 
esempio è il seguente: 



<?xml version = "1.0"?> 



<!DOCTYPE cross-domain-policy 

SYSTEM 

"http://www.macromedia.com/xml/dt 

ds/cross-domain-policy.dtd> 



<cross-domain-policy> 



<allow-access-from 
domain = 



'/> 



</cross-domain-policy> 



<redattore> 



<nome>Fabio</nome> 



<cognome>Farnesi</cognome> 



</redattore> 



<redattore> 



<nome>Gianfranco</nome> 



<cognome>Forlino</cognome> 



</redattore> 



<redattore> 



<nome>Domenico</nome> 



<cognome>Pingitore</cognome> 



</redattore> 



<redattore> 



<nome>Domenico</nome> 



<cognome>Pingitore</cognome> 



</redattore> 



</redattori> 

Il nostro scopo è creare un'applicazione Flash 
che stampa questi dati in una griglia prelevan- 
doli dal risultato fornito dal file PHP. 

Il codice mxml è il seguente: 

<?xml version = "1.0" encoding = "utf-8"?> 
<mx:Application 

xmlns:mx= "http://www.adobe.com/2006/mxml" 

layout="absolute" 

creationComplete="userRequest.send()"> 

<mx:HTTPService id = "userRequest" 

url = "http://172.16.0.241/work/flex/index.php" 

useProxy = "false" method = " POST" > 

</mx:HTTPService> 

<mx:DataGrid x="38" y="192" width="401" 
dataProvider="{userRequest.lastResult. 
redattori, redattore}" > 
<mx:columns> 







<mx 


DataGridColumn 

headerText="Nome" 
dataField = "nome"/> 






<mx 


DataGridColumn 

headerText= "Cognome" 








dataField = "cognome 


'/> 






</mx 


:columns> 






</mx 


DataGrid 


> 




</mx 


Application> 







Anche in questo caso il funzionamento è intuiti- 
vo. Nella riga 

<mx:Application 

xmlns:mx= "http://www.adobe.com/2006/mxml" 

layout="absolute" 
creationComplete="userRequest.send()"> 

Facciamo in modo che appena la creazione 
dell'applicazione è completata venga richia- 



► 26 /Settembre 2006 



http://www.ioprogrammo.it 



Programma in XML ottieni FLASH ■ T ioProgrammo Web 



mato il metodo send() dell'oggetto 
userRequest. L'oggetto in questione richiama il 
file PHP che abbiamo precedentemente creato, 
con la riga: 

<mx:HTTPService id = "userRequest" 

url = "http://172.16.0.241/work/flex/index.php" 
useProxy= "false" method = "POST"> 

Ed eventualmente gli passa dei dati tramite un 
POST. A questo punto instanziamo una Datagrid 

<mx:DataGrid x="38" y="192" width = "401" 

dataProvìder="{userRequest.lastResult. redattori. 

redattore}" > 

Che viene riempita, grazie al dataprovidere, con 
i dati prelevati dalla struttura XML definita dal 
file PHP scendendo nell'albero XML fino alla 
gerarchia redattore. redattore. A questo punto 
non dobbiamo fare altro che riempire le colonne 
con i Field nome e cognome. 



EFFETTUIAMO UHI POST 

Quello che faremo in questo paragrafo sarà 
estendere l'esempio precedente, consentendo 
all'utente di inserire un nuovo dato nel DB. Il 
primo passo sarà modificare leggermente il file 
PHP. Il codice da aggiungere è il seguente 



<mx:columns> 



if($ 


_POST[" 


nome"] AND $_POST["cognome"]) 


{ 




//add th 


e user 








$Query 


= "INSERT INTO redazione VALUES (", 
'$_POST[nome]', '$_POST[cognome]')"; 




mail("jaco@localhost". 


pippo 


,$Query); 




$Result 


= mysql_query( $Query ); 




} 


Mentre il file msxml diventa 



<mx:Application 

xmlns:mx= "http://www.adobe.com/2006/mxml" 

layout="absolute" 

creatìonComplete= "userRequest. send()"> 

<mx:HTTPService id = "userRequest" 

url = "http://172.16.0.241/work/flex/index.php" 

useProxy= "false" method = "POST"> 

<mx:request xmlns=""> 

<nome>{thename.text}</nome> 
<cognome> {su marne. text}</cognome> 
</mx:request> 



</mx:HTTPService> 



<mx:DataGridColumn 
headerText="Nome" data Field = "nome"/> 
<mx:DataGridColumn 

headerText= "Cognome" 
dataField = "cognome"/> 
</mx:columns> 
</mx:DataGrid> 
<mx:TextInput x="38" y="38" id = "thename"/> 
<mx:TextInput x="38" y="91" id = "surname"/> 
<mx:Button x="38" y="147" label = "Button" 

clìck= "userRequest. send()"/> 
</mx: Application > 

Vediamo di comprendere le linee più oscure. In 
particolare 

<mx:request xmlns=""> 

<nome>{thename.text}</nome> 
<cognome>{surname.text}</cognome> 
</mx:request> 

Queste due linee effettuano un "Bind" tra il con- 
tenuto di tue caselle di testo e le due variabili 
che verranno passate in POST. 
Le seguenti due linee 



<mx:TextInput x="38" y="38" 


id = "thename"/> 


<mx:TextInput x="38" y="91" 


id = "surname"/> 



<mx:DataGrid x="38" y="192" width = "401" 
dataProvider="{userRequest.lastResult. redattori. 

redattore}" > 



Rappresentano le caselline di testo da riempire e 
che sono bindate con il metodo precedente. 
Infine 

<mx:Button x="38" y="147" label = "Button" 

clìck= "userRequest. send()"/> 

Non fa altro che richiamare nuovamente la send 
di userRequest passandogli questa volta i para- 
metri nome e cognome in POST. Quando la 
richiesta arriva al file PHP. Tutto quello che è 
necessario fare è controllare se c'è un qualche 
valore presente in POST e se questo valore esiste 
effettuare l'update sul database. 



CONCLUSIONI 

Per questa volta ci fermiamo qui. Flex2 è uno 
strumento assolutamente rivoluzionario che 
modifica molto il modo di concepire e pensare 
un'applicazione. Non solo il modo di program- 
mare è sufficiente vicino a quello tradizionale, 
ma vengono rispettati anche i canoni di multi- 
piattaforma e separazione dell'interfaccia dalla 
logica di business. Per molti versi si potrebbe 
dire che Flex ha raggiunto in pochissimo tempo 
quello che Java rincorre da anni. 




http://www.ioprogrammo.it 



Settembre 2006/ 27 ► 



ioProgrammo Web T ■ Alla scoperta del Google Web Toolkit 



PROGRAMMA AJAX 
SECONDO... GOOGLE! 

AL GRAN NUMERO DI FRAMEWORK PER SVILUPPARE APPLICAZIONI WEB IN TECNOLOGIA AJAX 
NON POTEVA MANCARE UN TOOLKIT SVILUPPATO DAL GIGANTE DI INTERNET IL GOOGLE WEB 
TOOLKIT SI PRESENTA CON QUALCHE CARTA IN PIÙ. VEDIAMO QUALE 




(é 



CD □ WEB 

googletoolkitzip 




*M 



J 



n 




H.I.I.1WJJJ. 



Li 



Java 



I GoogleWebToolkit, 
JDK 1.4.2, Eclipse, 




AJAX (Asynchronous Javascript And 
XML) è senz'altro la tecnica del 
momento; oramai esistono framework 
per la scrittura di applicazioni Web che usano 
AJAX in tutti i maggiori linguaggi di program- 
mazione. Google è in prima linea nello svilup- 
po di applicazioni AJAX (basti pensare che sia 
Google Earth che Google Maps l'adottano) e 
ha reso disponibile un framework a suo modo 
rivoluzionario: esso non espone metodi che 
"incapsulano" le funzionalità volute; piutto- 
sto fornisce un nuovo Java Runtime 
Enviroment (JRE) per Java ed un insieme 
completo di API che permettono di realizzare 
applicazioni Java stand-alone. Lo sviluppo di 
queste applicazioni (e il debug) è possibile 
con un qualsiasi IDE, per esempio Eclipse, e, 
solo successivamente, un compilatore (forni- 
to insieme al framework) trasforma l'intera 
applicazione Java in una equivalente applica- 
zione Html + Javascript! 



GOOGLE WEB TOOLKIT 

Il framework si chiama Google Web Toolkit 
(d'ora in poi GWT), la cui pagina di riferimen- 
to è http://code.qooqle.com/webtoolkit/ ; esso è 
disponibile sia per piattaforme Windows sia 
Linux. Si compone di una serie di librerie (per 
l'emulazione di un ambiente Java) e di un 
compilatore. Il risultato del compilatore è 
un'applicazione Web che fa uso solo di tecno- 
logie client standard (DHTML) e che, eventual- 
mente, può interagire con un server per il repe- 
rimento dei dati. Tale reperimento non avviene 
attraverso l'usuale navigazione (e quindi il 
reload di pagine) ma usando delle chiamate 
RPC (Remote Procedure Cali) e l'aggiornamen- 
to della pagina corrente mostrata sul browser; 
questo fa sì che l'utente abbia la sensazione di 
usare un'applicazione standard (all'interno del 
browser) più che una usuale applicazione Web 
dove, di solito, si susseguono pagine diverse. 



DOWNLOAD E 
INSTALLAZIONE 

Dalla pagina http://code.google.com/webtoolkit/ 
download.html è possibile eseguire il download del 
framework. Di seguito saranno mostrati l'installa- 
zione e l'uso della versione per Windows (quella per 
Linux è del tutto simile) e la creazione di un nuovo 
progetto con Eclipse. Una volta scompattato l'archi- 
vio compresso, si ha un ambiente come quello illu- 
strato in Figurai. 





- t cffl 




Documenti 


{ 


..y index, html 
.4& about.hr.rnl 






about.txt 








&? gwt-dev-windows , jar 
^Èipgwt-ijser.jar 


| Librerie di 
i classi Java 


Comandi 
di utilità 


{ 


TjapplicationCreator.cmd 
TliunitQeator.cmd 
_jT] projectCreat or . cmd 


Documentazione 


K\ swt-win32-3139.dll 
^Igwt-ll.dll 


1 DLL per il 
> browser 
J builHn 


(API e tutoria 


i-i 


* + _j doc 














di esempio 



Fig. 1: la struttura del toolkit 



GLI ESEMPI 

Sotto la cartella samples/ è possibile accedere a 
degli esempi d'uso del framework. La loro struttura 
è la seguente: 

a) nella cartella principale di ogni esempio ci sono 
due script: uno per eseguire la compilazione 
(ovvero per compilare le classi Java e trasformar- 
le in file DHTML) ed uno per lanciare un browser 
particolare, chiamato "hosted"; 

b) una cartella contenente i file sorgente dell'esem- 
pio (la cartella è src/); 

e) una cartella con i file .class risultato della compi- 
lazione dei sorgenti (cartella bin/); 

d) una cartella contenente i file compilati in pagine 
DHTML (cartella www/); 



► 28 /Settembre 2006 



http://www.ioprogrammo.it 



Alla scoperta del Google Web Toolkit H T ioProgrammo Web 



UM PROGETTO 
IIU ECLIPSE 

Si supponga di voler utilizzare l'IDE Eclipse per la 
gestione di un progetto (si farà uso di Eclipse 3.1 con 
plug-in WebTool Project). In particolare si vuole far sì 
che il progetto contenga uno scheletro iniziale in cui 
sono impostati tutti i riferimenti alle librerie e in cui 
sia creata la classe principale, chiamata "modulo". Si 
apra una shell di comandi, ci si posizioni sulla cartel- 
la di installazione del GWT; quindi si digitino i 
comandi che seguono. Dapprima è necessario setta- 
re il patii della cartella workspace (dove si trova 
Eclipse nel vostro sistema): 

set PATH_WORKSPACE=D:\path\to\eclipse\workspace 

Poi bisogna settare il nome del progetto da creare 
(nell'esempio esso è IoProgrammoGwt): 

set NOME_PPJ=IoProgrammoGwt 

Quindi va settato il nome del package dei file sorgen- 
te: 

set PACKAGE=it.ioprogrammo 



Non resta che aprire Eclipse; quindi scegliere New > 
Project > Java Project. Nella finestra di dialogo speci- 
ficare lo stesso nome inserito nella variabile 
NOME_PRJ. Eclipse si accorge che tale progetto esi- 
ste e avverte che verrà incluso. Basterà premere sul 
pulsante "Finish" per avere il nuovo progetto inclu- 
so tra quelli aperti. 

Non resta che eseguire lo scheletro così creato (infat- 
ti, benché minimale, è stata creata un'applicazione 
completa). Per farlo si scelga Run > Run.... Nella fine- 
stra di dialogo ci dovrebbe essere IoProgrammoGwt, 
come mostrato in Figura 3. 









Fig. 3: finestra di dialogo per eseguire l'applicazione 



LE VERSIONI 
DEL TOOLKIT 

Al momento di 
scrivere l'articolo la 
versione disponibile 
del GWT è la 1.0.21, 
che è considerata 
ancora una "beta 
release". Pertanto, non 
ancora adatta 
ad un ambiente 
di produzione. 



La creazione vera e propria avviene invocando due 
script shell; il primo serve a creare la struttura del 
progetto: 

projectCreator -eclipse %NOME_PRJ% 
-OUt %PATH_WORKSPACE%\%NOME_PPJ% 

Il secondo serve a creare l'ossatura di base conte- 
nente dei file sorgente (da estendere per creare l'ap- 
plicazione vera e propria): 

applicationCreator -eclipse %NOME_PPJ% 
-OUt %PATH_WORKSPACE%\%NOME_PPJ% 
%PACKAGE%.client.IoProgrammoGwt 



L'esecuzione dell'applicazione consiste nell'aprire il 
browser hosted e l'applicazione appena creata 
(Figura 4). 



B Jt 


.JLJL £ &=.** 








i * * ii 


e**. 




i 




IoProgrammoGwt 

Ttw n m «HTTk <f p htm piotfcr th* tAnonpinDGri «wtc*<r- Voti oiataAa W* fooUtiKi* 
to «VHTh*. ma wbb «-» nahng < MS* KeVM 1 ■ W u tali II liaaiUi ééMii i pao« WDteul *axj 
■em «tatti 

a.» 



Fig. 4: esecuzione dell'applicazione creata 



Aprendo la cartella specificata precedentemente in 
PATH_WORKSPACE si può osservare che è stata 
creata un'applicazione con la struttura mostrata in 
Figura 2. 



SUPPORTO DI JAVA 



U ^ IoProgrammoGwt 

^ .dasspath 

5^ .project 

;Ea1 IoProgrammoGwt. launch 

TI IoProgrammoGwt-compile.cmd 

TJ IoProgrammoGwt-shell.cmd 

- ) src 

B <_3 it 

- | ioprogrammo 

'^1 IoProgrammoGwt. gwt. xml 

, client 
^p IoProgrammoGwt. java 
- _j public 

40 IoProgrammoGwt.html 



Fig. 2: la struttura dell'applicazione creata 



GWT permette di compilare 
programmi scritti in Java 1.4.2 (o 
successive versioni). Vengono 
emulate le classi contenute nei 
package java.lang e java.util (per 
la cui documentazione specifica, 
comprese eventuali limitazioni, si 
rimanda alla documentazione 
delle API). Esistono alcune 
limitazioni anche sui costrutti 
Java supportati ma che sono, in 
genere, del tutto marginali. Per 
esempio non è possibile 
utilizzare i metodi di reflection 
propri di Java (cali by name, 
introspezione e altro); inoltre i 



tipi di dato a 64 bit sono 
"simulati" con tipi JavaScript a 
doppia precisione; si raccomanda 
anche una certa cautela nell'uso 
delle espressioni regolari, in 
quanto esse sono gestite in 
maniera leggermente diversa tra 
Java e JavaScript. GWT, infine, 
non supporta la serializzazione 
delle classi e le asserzioni e i 
costrutti di sincronizzazione sono 
ignorati nel codice risultante 
(perché il programma JavaScript 
ottenuto non è mai multithread, 
essendo eseguito su un unico 
client alla volta). 



http://www.ioprogrammo.it 



Settembre 2006/ 29 ► 



ioProgrammo Web T I Alla scoperta del Google Web Toolkit 




Verificato che tutto è andato a buon fine si può pro- 
cedere nell'ispezione del codice sorgente creato in 
automatico e, successivamente, si può personaliz- 
zarlo. Per esempio si provi ad aprire il file it.iopro- 
grammo.client.IoProgrammoGwt.java e a cambiare 
il contenuto delle scritte (mettendole, per esempio, 
in italiano). Rieseguendo il run del programma ecco 
che appaiono subito le nuove modifiche. 



componenti (pannelli o altricontenitori) ma 
tutti, alla fine, dovranno essere agganciati al 
componente RootPanel. Ma a chi si riferisce 
questo RootPanel? Esso non è altro che la pagina 
HTML di partenza. È interessante notare che l'e- 
sempio creato di default fa riferimento a due 
entità specifiche ("sloti" e "slot2") a cui aggan- 
cia i componenti creati: 




RootPanel. get("slotl").add(button); 



L PATH DI INSTALLAZIONE 



I comandi contenuti in GWT per 
la creazione del progetto in 
Eclipse inseriscono, tra le 
proprietà del progetto, dei 
riferimenti alla cartella di 
installazione del toolkit stesso. 
Se si desidera procedere alla 
creazione ex-novo del 
progetto, seguendo i passi 
descritti nell'articolo, lo si può 
installare dove si preferisce; 
viceversa, per minimizzare i 
cambiamenti al progetto 
esistente, si consiglia di 
installare il toolkit nella 
cartella c:\gwt-windows\ 



(oppure intervenire da Eclipse 
usando Project > Properties > 
Java Build Path > Libraries e sui 
file .cmd e .launch). Inoltre, di 
default, il progetto è settato 
per essere eseguito in locale 
(senza comunicare via RPC con 
una parte server). Per cambiare 
questo comportamento si deve 
intervenire sulla classe 
loProgrammoGwt.java e 
impostare a "true" la variabile 
SERVER SIDE e inserire in 
SERVER SERVICE URL la uri 
completa a cui risponde il 
servizio lato server. 



J 




USIAMO 
IL SINGLETON 

Il pattern Singleton 

permette di creare un 

unico oggetto di una 

classe e di riferirlo 

nelle altre classi senza 

creare nuovi oggetti (è 

pattern molto usato 

nelle applicazioni 

GWT). 



ANALISI DEL CODICE 
SORGENTE 

Il vantaggio dell'uso di un IDE come Eclipse si 
apprezza da subito: basta selezionare (doppio 
click) una qualsiasi delle classi o metodi (per 
esempio Button) e poi premere con il pulsante 
destro e scegliere, dal menu contestuale, "Open 
Declaration": subito appare la definizione della 
classe (o del metodo). In questo modo si può 
ispezionare il codice esistente e capirne il conte- 
nuto "by example". In particolare è possibile 
verificare che la classe IoProgrammoGwt imple- 
menta l'interfaccia EntryPoint, la quale ha un 
unico metodo: onModuleLoadf). Leggendo la 
documentazione si scopre che questo è il meto- 
do invocato quando il modulo viene caricato 
(nel linguaggio GWT un modulo è un'applica- 
zione). 

Si può anche osservare che alla classe Button, 
come a tutte le altre classi che sono componenti 
dell'interfaccia, è possibile associare dei listener; 
in pratica il listener viene invocato al verificarsi 
di particolari eventi (se si usa un ClickListener, 
esso intercetta la pressione di un tasto del 
mouse, FocusListener quando riceve il focus e 
KeyboardListener intercetta eventi proveniente 
dai tasti della tastiera). Inoltre ciascun compo- 
nente creato può essere agganciato ad uno o più 



RootPanel. get("slot2").add(label); 

Basta aprire il file it.ioprogrammo. public. 
IoProgrammoGwt.html e ispezionare codice 
per accorgersi che essi fanno riferimento a due 
entità html contrassegnate con un ID omonimo: 

■ctable align=center> 

<tr> 

<td id="slotl"x/tdxtd id="slot2"x/td> 

</tr> 
</table> 

Se, anziché riempire una tabella esistente (e 
fissa!) si vuole generare tutto il contenuto dina- 
micamente, il body html deve essere vuoto. 
Un'altra cosa interessante, che deriva dall'anali- 
si del file html, è che il link tra questa pagina (che 
rappresenta la pagina inziale e una sorta di 
"template" per la parte AJAX vera e propria) e il 
relativo modulo GWT è dato da un tag meta pre- 
sente nell'intestazione: 

<meta name='gwt:module' 

content= 'it.ioprogrammo. IoProgrammoGwt' > 



LA NUOVA APPLICAZIONE 

È giunto il momento di creare un'applicazione del 
tutto nuova. Questa prevede la creazione di un 
visualizzatore di... questo articolo! Ovvero si vuole 
un menu a sinistra con i titoli delle diverse sezioni: 
facendovi clic sulla destra appare il testo completo 
relativo alla sezione selezionata. In alto una sempli- 
ce intestazione con il titolo e l'autore, insieme al 
catenaccio. Il nuovo metodo onModuleLoad 
potremmo riscriverlo come segue: 

public void onModuleLoad() { 
DockPanel main = new DockPanel(); 
main.add(getTitolo() , DockPanel. NORTH); 
main.add(getAutore() , DockPanel. NORTH); 



main.add(getCatenaccio() , 



DockPanel. NORTH); 



main.add(getMenuSinistra() , 



DockPanel.WEST); 



main.add(getSezioniDestra(), 



► 30 /Settembre 2006 



http://www.ioprogrammo.it 



Alla scoperta del Google Web Toolkit H T ioProgrammo Web 



DockPanel.CENTER); 



main.setWidth("100%"); 



RootPanel.get().add(main); 



In pratica si usa un pannello (DockPanel) a cui è 
possibile "attaccare" nuovi widget grafici su uno 
dei bordi (usando le opportune costanti che 
indicano i quattro punti cardinali) e l'ultimo 
widget agganciato prenderà la parte restante al 
centro. Il metodo getTitolo reperisce il titolo 
come immagine, getAutore, l'autore come testo 
HTML e getCartenaccio come Label (per i detta- 
gli dei metodi si veda il codice sorgente allega- 
to). Più interessanti i metodi getMenuSinistraO 
e getSezioni Destra() che, rispettivamente, 
mostrano la lista delle sezioni, ognuna con 
un'immagine di riferimento, e il testo completo 
della sezione selezionata. 

Il menu a sinistra viene realizzato mediante un 
oggetto di tipo Tree (albero in cui i nodi sono 
label più immagine). L'oggetto che visualizza 
testo può essere un semplice testo html con la 
possibilità di scroll. Inoltre è necessario far sì 
che un clic sul menu a sinistra coincida con il 
cambio del testo visualizzato nella sezione a 
destra. Per far questo è necessario eseguire un 
design particolare per l'applicazione (se si fa 
riferimento agli esempi standard è, più o meno, 
quanto realizzato nell'esempio Mail). 



SINGLETON 

Si possono creare due classi distinte, una che 
implementi la lista delle sezioni (quella a sini- 
stra) e una che implementi la visualizzazione 
della sezione corrente (al centro) . Chiamiamo la 
prima ListaSezioni. Essa estenderà la classe 
Composite, ovvero una classe che permette di 
eseguire il wrapping di un qualsiasi componen- 
te: in questo caso si vuole fare il wrapping di un 
oggetto Tree (che pertanto verrà dichiarato 
come attributo privato della classe stessa). 
Inoltre ListaSezioni implementerà l'interfaccia 
TreeListener, in quanto si vuole eseguire l'ag- 
giornamento del testo mostrato al centro quan- 
do c'è un clic su uno degli elementi del Tree. Il 
costruttore della classe prenderà la lista delle 
sezioni e le disegnerà come link associati all'og- 
getto Tree (per comodità tutte le informazioni 
specifiche alle sezioni, ovvero titoli e testo asso- 
ciato, sono state racchiuse in una classe di utilità 
chiamata Sezioni). 

Ora è necessario realizzare il metodo che inter- 
cetti il clic su un titolo e agisca sul componente 
al centro. Come far interagire i due? Un modo è 
il seguente: far sì che il modulo principale 



(IoProgrammoGwt) diventi un singleton, sia 
referenziato dal gestore dell'evento e invochi un 
apposito metodo di aggiornamento: 

public void onTreeItemSelected(TreeItem item) { 
IoProgrammoGwt.getInstance(). 
setSezione( testo ); 



} 



A questo punto il metodo setSezione non farà altro 
che invocare un metodo della seconda classe, quel- 
la responsabile del disegno a video del testo (classe 
MostraSezione.java) a cui passa il testo inserito dal 
gestore dell'evento clic. 

Non resta che eseguire il progetto e verificare che 
l'applicazione si comporti nel modo voluto. 



PER ORA E SOLO CLIENT! 

L'applicazione appena sviluppata in realtà non 
interagisce mai con un server remoto; infatti la 
classe Sezioni.java memorizza al suo interno 
tutte le informazioni riguardanti i titoli e i testi 
delle sezioni. Questa va bene se si vuole esegui- 
re un test delle funzionalità client. Di solito inve- 
ce, per applicazioni complesse, questa parte 
dovrebbe reperire le informazioni su un server 
attraverso chiamate RPC. GWT impone una 
struttura rigida per creare le classi lato client e 
lato server che devono essere messe in comuni- 
cazione via chiamate RPC. Questa "rigidità" è 
dovuta al fatto che lo sviluppatore si concentra 
sulle funzionalità, mentre è compito del toolkit 
(grazie alla reflection) creare il meccanismo di 
invocazione RPC, con relativa serializzazione 
/deserializzazione dei parametri e quant' altro è 
necessario per il suo corretto funzionamento. 
Ecco come procedere per comunicare i dati da 
client a server (e viceversa) . 



RPC: INTERFACCE 
E CLASSI SUL CLIENT 

La prima cosa da realizzare è un'interfaccia. Essa 
deve estendere la classe RemoteService e dichiarare 
tutti i metodi che si vuole invocare sul server; per il 
nostro esempio essa può essere la seguente: 



public interface SezioniService extends 



RemoteService{ 



public String[] getTitoliQ; 



public String getSezione(String titolo); 



} 



Questa interfaccia rappresenta il "contratto" del 
servizio; come tale dovrà, successivamente, essere 




ECLIPSE 
ED I PATH 

Per impostare dei path 
personalizzati su 
Eclipse, si usi Project > 
Properties > Java Build 
Path > Libraries; 
inoltre intervenire sui 
file .cmd e .launch 



ATTENTI 
A TOMCAT 

La libreria gwt-user.jar 
ridefinisce la gerarchia 
javax.servlet. Per 
questo non può essere 
inclusa in una webapp 
ma deve essere resa 
accessibile nella 
cartella 

STOMCAT HOME/comm 
on/endorsed/ 



http://www.ioprogrammo.it 



Settembre 2006/ 31 ► 



ioProgrammo Web T I Alla scoperta del Google Web Toolkit 




importata anche sulla parte server. Il client deve } 
definire una seconda interfaccia; essa deve avere lo 
stesso nome della precedente ma con suffisso 
Async; inoltre i metodi sono gli stessi di quelli della 
classe precedente ma, questa volta, non restituisco- 
no alcun valore e hanno un parametro in più, di tipo } 
AsyncCallback: }; 



public void onFailure(Throwable caught) { 
IoPrograrnmoGwt.getInstance().setSezione( 



"Impossibile contattare il server;" 



+caught.getMessage()); 



public interface SezioniServiceAsync { 
public void getTitoli(AsyncCallback callback); 
public void getSezione(String titolo, AsyncCallback 

callback); 



Infine non resta che invocare il metodo asincrono 
passando gli opportuni parametri (l'ultimo dei quali 
è sempre l'oggetto AsyncCallback creato nelle righe 
precedenti, mentre i restanti parametri sono quelli 
utilizzati nell'interfaccia SezioniService): 




E LA PRIVACY? 

Monitorando le 

connessioni in uscita ci 

si accorge che la 

libreria comunica dei 

dati verso un server di 

Google; così verifica la 

presenza di 

aggiornamente e 

aggiorna le statistiche 

d'uso della libreria. 




Per invocare un metodo sul server, è necessario 
costruire un opportuno oggetto dell'ultima interfac- 
cia (SezioniServiceAsync) e, per costruirlo, si deve 
utilizzare una apposita factory (GWT.create) a cui si 
passa la classe dell'interfaccia SezioniService: 

SezioniServiceAsync sez = 
(SezioniServiceAsync) 

GWT.create(SezioniService. class); 

Inoltre si deve impostare l'end-point (che è una uri 
espressa come stringa di caratteri) a cui risponde il 
servizio: 



ServiceDefTarget endpoint = (ServiceDefTarget) 



sez; 



endpoint.setServiceEntryPoint( qualeUrl ); 

Si vedrà in seguito come impostare questa uri del- 
l'end-point. Resta da effettuare l'invocazione RPC 
vera e propria. Tale invocazione è sempre asincrona, 
per quanto concerne la parte client. In particolare è 
necessario creare un oggetto AsyncCallback, nel 
quale ci sono due metodi: onSuccess (che viene 
invocato al completamento del metodo quando 
tutto è andato a buon fine) e onFailure (invocato, per 
esempio, quando il server non risponde o in tutte le 
situazioni "anomale"); ecco un esempio 

AsyncCallback callback = new AsyncCallbackQ { 
public void onSuccess(Ob]ect result) { 
IoProgrammoGwt.getInstance().setSezione 

(""+result); 



PC: CLASSI SUL SERVER 



La classe principale sul server 
(nell'esempio 

SezioniServicelmpl.java) è una 
servlet molto particolare; infatti 
essa deve estendere la classe 
RemoteServiceServIet e 
implementare l'interfaccia voluta 
definita in precedenza sul client 
D'esempio essa è 



(ne 



SezioniService). 

Questa, SezioniServicelmpl.java, 
è l'unica classe da realizzare a 
livello di server (ovviamente si 
consiglia sempre di separare la 
logica di accesso ai dati su una 
classe ausiliaria, ma questo è un 
suggerimento di design che si 
può anche ignorare). 



sez.getSezione(valoreDaSettare, callback); 

Per la parte client il lavoro è concluso. L'invocazione 
vera e propria viene interamente gestita dal fra- 
mework. Non resta che realizzare le classi server che 
espongono il servizio richiesto; questa operazione è 
ancor più semplice di quanto fatto per la parte 
client... 



TEST IM "LOCALE" 

Avendo realizzato tutte le classi nel progetto origina- 
rio, è possibile eseguire il test semplicemente inse- 
rendo un tag <servlet ... /> nel file di configurazione 
del progetto dove specificare, rispettivamente, la uri 
della servlet che risponde in locale e la classe che la 
realizza; per l'esempio il file da personalizzare è 
src\it\ioprogrammo\IoProgrammoGwt.gwt.xml: 

<module> 



<!- 



altri tag 



<servlet path="/SezioniService" 



class="it.ioprogrammo.server.SezioniServiceImpl" 



/> 



</module> 

Ovviamente nel path a cui far rispondere la servlet si 
può scegliere un qualsiasi nome. In ogni modo il 
valore di tale path è quello che va inserito come end- 
point del servizio sulla classe client che si occupa di 
creare l'oggetto SezioniServiceAsync. Ora è possibile 
rieseguire l'applicazione e verificare che funzioni 
anche in questa modalità. 



TEST REMOTO 

Benché il test in locale sia utile in fase di debug 
è necessario creare un progetto separato che 
realizzi la parte server del servizio e testarlo 
usando i due progetti come due applicazioni 
distinte (chiamiamo questa fase "test remo- 
to"). Per farlo si crei un progetto "Dynamic 



► 32 /Settembre 2006 



http://www.ioprogrammo.it 



Alla scoperta del Google Web Toolkit H T ioProgrammo Web 



Web Project" con Eclipse e si copino le classi 
necessarie alla realizzazione della parte server 
create in precedenza (interfaccia Sezioni 
Service.java e la servlet SezioniService 
Impl.java); inoltre è necessario copiare il file 
gwt-user.jar nelle librerie del progetto. 
Attenzione al fatto che questo file non viene 
letto da Tomcat al momento del deploy! Infatti 
il jar contiene una ridefinizione della gerarchia 
javax.servlet e, per questo, ignorata dal contai- 
ner (per ragioni di sicurezza). Per questo moti- 
vo è indispensabile copiare il file jar nella car- 
tella $TOMCAT_ HOME/common/endorsed/ 
prima di eseguire il deploy della webapp. 
L'ultima modifica necessaria è la personalizza- 
zione del file web. xml affinché si dichiari la 
servlet del servizio e l'uri a cui essa debba 
rispondere; per esempio: 



<servlet> 


<servlet-name>SezioniService</servlet-name> 


<servlet-class> 


it.ioprogrammo.server.SezioniServicelmpI 


</servlet-class> 


</servlet> 


<servlet-mapping> 


<servlet-name>SezioniService</servlet-name> 


< uri-pattern >/Sezio 


iiService</url-pattern> 


</servlet-mapping> 



installare tcpTrace (http://www.pocketsoap. 
com/tcptrace/). Esso non fa altro che mettersi 
in ascolto su una porta e redirigere quanto 
riceve su un'altra (per esempio si può mettere 
Tomcat in ascolto sulla porta 8081, intercettare 
le richieste applicative indirizzate sulla porta 
8080 e, con tcpTrace, redirigerle sulla porta 
8081). In Figura 5 un esempio di comunicazio- 
ne tra client e server; si possono notare alcune 
cose, come il fatto che la comunicazione è 
mantenuta attiva anche al termine dell'intera- 
zione e che i contenuti sono in formato binario 
per ottimizzare il flusso dei dati. 



SI COMPILA! 

Completato l'esempio non resta che compilar- 
lo in codice DHTML. Per farlo basta mandare 
in esecuzione lo script chiamato IoProgrammo 
Gwt-compile.cmd (nella root del progetto). 
Esso crea automaticamente la cartella www/ 
con il codice compilato. Aprendolo con un 
qualsiasi browser appare l'applicazione prece- 
dentemente creata ma che fa uso, per la parte 
client, di solo codice DHTML (Figura 6). 

Ivan Venuti 




INTERFACCE 
CUSTOM 

È possibile 

personalizzare il layout 
del codice DHTML 
generato intervenendo 
solo sui CSS. La 
documentazione delle 
API specifica gli stili 
associati ai diversi tag. 



Tutto a posto? Quasi! Bisogna modificare l'end- 
point sul client; in particolare è necessario 
inserire una uri al servizio remoto (composta 
da nome del server o indirizzo ip, porta, nome 
applicazione e path a cui risponde la servlet); 
un esempio potrebbe essere http:// 127.0.0.1: 
8080/IoProgrammoGwtServer/SezioniService. 



MONITORARE IL TEST 

Siccome fidarsi è bene, ma non fidarsi è 
meglio, vogliamo curiosare soprattutto nella 
comunicazione tra l'applicazione e il server, si 
installerà un monitor; per esempio si può 







Arai. [ASvndrwi JevKftipt Anrt XhLt è EStCAd la iBciiea del momento, 
4Knnitf> vuahTnnirt am * ^S*™ nwwNUrtk par S *oBftrB o> appcrawWobd quatti tipo in 
■^^ tm i megfliofi nguaggi di pTOffaFiiiitìawie Google, oa sempre moto 

'SttOonod Java i«ftswa?>^iped*ppi£i0M(t^p«riHrt^(i«G<^EA£iw 
+ GooojaMÉ|sr&ctMiar»)rBr«»oi5p^ 

mtiuB<xwa «» non «tpm marad d» 'ireipalfliicr It tunpeima veàu 

(nW(Iie¥gW«iWIQU0!Ml»«n^b«wW^ 



luCcHMVàrìtnlt.iai compi Uoi* di* trattami fin 



Fig. 6: l'applicazione, compilata in DHTML, come 
appare in Firefox 



H™ 



ini 



IM lui ■ POS.1 PnPtn r mm 



Tr«a3jted. ttUntPH - : 



Arc<fi1'L*na>»fefle: >ttn^ Q^.evq Q! 
nefriti: bflpJJuc.l^.uiMBiMfl.lijp'-i'"! 
x-!Mt*Hln*mo*yle: *.\apt*v*n\m*.\aPr 
t*riìrw I fft: kextfp«iln; (hu iti wtl I 



111 TI?! .1 7fDCHI 

Sriwi ApMfcrCuy^rJ'l 1 

CHrlEnH.4iEcdl(m: g z ip 



t q* jwn znu IFtMzWWI 



CwHeM-Twf: Ir*Vp*iln:ch*w1 **l 



Fig. 5: tcpTrace ci rivela la comunicazione tra il client 
e il server. 




APPROFONDIRE... 



Google offre un forum di 
discussione specifico per GWT 
(accessibile alla pagina 
http://groups.google.com/group/ 
Google-Web-Toolkit) dove poter 
chiarire eventuali dubbi o 
esporre le difficoltà incontrate, 
e un blog (pagina 
http://googlewebtoolkit.blogsp 

V 



ot.com/) dove è possibile 
restare aggiornati sulle ultime 
novità del framework. Essendo 
il framework ancora in versione 
beta, ci si aspetta un rapido 
susseguirsi di nuove versioni e, 
perché no, di funzionalità 
sempre più sofisticate. Stay 
tuned! 



http://www.ioprogrammo.it 



Settembre 2006/ 33 ► 



ioProgrammo Web T ■ Programmare con le Web Parts 



USARE IL BROWSER 
COME DESKTOP 

UNA DELLE NOVITÀ PIÙ INTERESSANTI DEL FRAMEWORK .NET 2.0 È SICURAMENTE QUELLA 
DELLE "WEB PARTS". SI TRATTA DI UN METODO CHE CONSENTE AD UN UTENTE DI COSTRUIRE 
DINAMICAMENTE UNA PAGINA WEB ADATTANDOLA ALLE PROPRIE PREFERENZE.... 



I al 



(é 



CD J WEB 

WebpartsDemo.zip 




*M 



n 



hahwjj; 



J 




Basi di Asp.net 



| Visual Studio 2005, 
framework . NET 2.0 



• 



Tempo di realizzazione 



Sono due i nuovi elementi dell'interfaccia 
che recentemente stanno modificando 
radicalmente il concetto di applicazione 
web: Ajax e le Web Parts. La prima è una tec- 
nologia che consente di creare siti che si 
aggiornano senza la necessità di Reload delle 
pagine. La seconda trasporta sul web il con- 
cetto di desktop tanto caro agli utilizzatori dei 
PC. L'idea è semplice, si deve pensare alla 
pagina web come una sorta di scrivania sulla 
quale disporre degli elementi. Gli elementi 
possono poi essere nascosti, spostati, mano- 
vrati come di consueto. Ad esempio immagi- 
nate una pagina web vuota, sulla quale l'uti- 
lizzatore (non il programmatore) può "pog- 
giare" la lista dei suoi RSS preferiti. Se riuscite 
a visualizzare quest'attività avete già capito 
più o meno qual è il concetto di Web Parts. 
Per meglio chiarire provate a fare una visita al 
sito live.com. In alto a sinistra è presente un 
menu che recita "imposta/nascondi", se lo 
cliccate nasconderete, oppure visualizzerete, 
la barra sottostante. Se, invece, provate a 
usare il pulsante: "Aggiungi Contenuti" sco- 
prirete che è possibile aggiungere dinamica- 
mente una "area" alla pagina. Ciascuna nuova 
"area" può racchiudere listbox, textbox, tabel- 
le o qualsiasi elemento che compone una tipi- 
ca pagina Web. In sostanza è possibile perso- 
nalizzare l'Home Page di live.com aggiungen- 
do, rimuovendo o spostando a piacimento 
queste particolari "aree", o per usare il termi- 
ne tecnico: "Web Parts". Le Web Parts, presen- 
ti anche su Google ed Msn, sono un ulteriore 
passo avanti verso il Web 2! 



WEB PARTS 
IIU PRATICA 

Asp.NET contiene una serie di controlli nativi 
che consentono di creare facilmente siti web 
che sfruttano profondamente le Web Parts. 
Generalmente possiamo dire che il Team della 



nuova release di asp.NET si è ispirato ad uno 
stile di programmazione "dichiarativo" anche 
nel progettare per le Web Parts ponendosi 
come scopo, di ridurre al minimo il codice da 
scrivere e gli algoritmi da pensare e limitando 
il compito dello sviluppatore all'assemblaggio 
di componenti che, in maniera trasparente, 
fanno, semplicemente, quello che dichiarano 
di fare. All'interno di una tipica Web Form la 
sintassi per creare una Web Parts è semplice 



<asp:WebPartZone ID = 


WebPartZonel" 


Runat= 


'server" > 


<ZoneTemplate> 






Qui va inserito 


un 


qualsiasi 


elemento della 


pa 


gina Web 


</ZoneTemplate> 






</asp:WebPartZone> 



Per essere precisi le Web Parts possono essere 
spostate solo in aree specifiche della finestra 
del browser denominate Web Zone; Nella Fig. 
1, che illustra l'esempio allegato all'articolo, 
potete vedere diverse zone colorate che rap- 
presentano appunto le Web Zone alle quali le 
Web Parts fanno riferimento. 



— - P :• * a ■ » * 



~| 



Cimimi Coi* ri uhi- 'rtvjafeM* ftil 



> * éi i ■_ i ii t m 



^toc«oor 



■ ■— — — — — <— — ■ 



Fig. 1: Le zone colorate rappresentano le Web zone 

Le Web Part possono essere modificate, ovve- 
ro possono essere spostate, editate, minimiz- 
zate ed altro solo se lo stato della pagina lo 



»> 34 /Settembre 2006 



http://www.ioprogrammo.it 



Programmare con le Web Parts H T ioProgrammo Web 



consente. Lo stato della pagina può essere 
programmato attraverso un evento innescato 
da un qualsiasi elemento dell'interfaccia 
utente: la pressione di un bottone, una voce 
selezionata da un DropDownList, eccetera. 
Ad esempio mostriamo uno spezzone di codi- 
ce che modifica lo stato della pagina in rela- 
zione al click su un bottone. 

"Gestore di un evento legato ad un pulsante 
Protected Sub Buttonl_C!ick(ByVal sender As 
Object, ByVal e As System. EventArgs) Handles 

Buttonl. Click 
Try 

"La pagina e' in modalità Catalog 
WebPartManagerl.DisplayMode = 
WebPartManager. Catalog Display Mode 



Catch ex As Exception 



LabelError.Text = 

Server. HtmlEncode(ex.Message) 



LabelError.Visible = True 



End Try 



End Sub 

In ogni momento lo stato della pagina può 
essere in uno dei seguenti stati 

Modalità Browse: Lo stato normale della 
pagina, nel quale nessun elemento può esse- 
re modificato 

Modalità Design: In questo stato è possibile 
spostare le Web Parts attraverso le Web Zone 
Modalità Catalog: In questo stato è possibile 
enumerare le Web Parts della pagina, aggiun- 
gerne ed eliminarne 

Modalità Edit: In questo stato è possibile con- 
figurare le Web Parts, ovvero è possibile pro- 
grammarne le dimensioni, le varie scritte, le 
relative icone, eccetera 



varie Web Parts presenti nella pagina, le 
aggiunge o le cancella; 



<J~ - ;. — —■ - e ■ . "3 •■» » 






— 




— ..— .r.^. 








— — 


^-j. - 




1g0mM '■'■ it* P.éh é crudi iv«t ApgUip ma Alti P«i m «uria *»t 


^iS^ 




**■«•■ "in ii - Sfilici 




1 -^.^«k— -..„-—- a™ i 








Fig. 2: Le web parts possono essere enumerate trami- 
te un controllo di tipo PageCatalogPart 



<asp:CatalogZone ID = "CatalogZonel" 

Runat="server"> 



<ZoneTemplate> 



<asp: PageCatalogPart 

Runat="server" 
ID="PageCatalogPartl" /> 



</ZoneTem piate > 



</asp:CatalogZone> 

In alternativa è possibile utilizzare il controllo 
DeclarativeCatalogPart che consente allo svi- 
luppatore di disegnare un Catalog personaliz- 
zato utilizzando le componenti preferite 

<asp: DeclarativeCatalogPart 
ID = "DCP1" 
runat="server"> 
<WebPartsTem piate > 

Inserisci I tuoi controlli qui 
</WebPartsTemplate> 
</asp:DeclarativeCatalogPart> 




INSERIRE 

O CANCELLARE 

Immaginiamo l'Home Page di un moderno 
sito di News: ci sono Web Parts che illustrano 
le principali notizie di cronaca, politica, 
moda, scienza ed altro. L'utente può non 
essere interessato alla moda ma desiderare di 
essere informato sullo sport, è opportuno 
prevedere quindi la personalizzazione delle 
Web Parts presenti nella pagina. Quando la 
WebForm è in modalità Catalog appunto, è 
possibile ordinare le varie Web Parts presenti 
nella pagina utilizzando il controllo 
PageCatalogPart. 

Questa funzionalità è ottenuta attraverso la 
maschera visibile in Fig. 2 che enumera le 



Nota che è possibile spostare Web Parts da 
una Web Zone all'altra non solo clickandovi 
sopra e trascinandole ma anche tramite il 
controllo PageCatalogPart perché questa fun- 
zionalità "Drag and Drop" non può essere 
implementata in tutti i modelli di browser. 



WEB PARTS 

COME WINDOWS FORM 

È possibile minimizzare chiudere, editare ed 
aprire la Web Parts attraverso un apposito 
menu, indicato nella Fig. 3 (nota la somiglian- 
za con il tipico menu delle Windows dei siste- 
mi operativi grafici); Concretamente questa 
funzionalità è implementata così: 



http://www.ioprogrammo.it 



Settembre 2006/ 35 ► 



ioProgrammo Web T I Programmare con le Web Parts 




<asp:WebPartZone ID = "WebPartZonel" 

Runat="server"> 
<CloseVerb Text="Chiudi" /> 
<HelpVerb Text="Help Online" /> 
<ExportVerb Text="Esporta WebPart 

Definition" /> 
<DeleteVerb Text ="Cancella " /> 
<MinimizeVerb Description = "Minimizza" /> 
<RestoreVerb Description = "Ripristina" /> 
<ZoneTemplate> 



</ZoneTem piate > 
</asp:WebPartZone> 



razione accurata della Web Parts 



I 



issgs 



'Vhwior 






Fig. 3: Le Web Parts possono essere minimazzate o 
espanse tramite semplici pulsantini 

Il nome in codice degli eventi gestiti da que- 
sto menu è Verbs. Per la precisione, se la pagi- 
na non è nella statica modalità Browse, è pos- 
sibile 



Minimizzare la Web Parts (MinimizeVerb). 
Riaprirla (RestoreVerb) 
Chiuderla (CloseVerb) 
Modificarla con i controlli dedicati che 
vedremo più avanti (EditVerb) 
Fare comunicare tra loro le Web Parts 
(ConnectVerb) 

Le Web Parts possono registrare la configu- 
razione delle loro proprietà in un file XML 
che può essere importato in modo che i 
relativi settaggi siano ereditabili 
(ExportVerb) 

Lanciare una guida, ovvero una pagina 
web dedicata, che spieghi come funziona 
la WebPart (HelpVerb) 



PERSONALIZZARE 
LA GRAFICA DELLE 
WEB PARTS 

Quando lo stato della pagina è in modalità 
Edit, ed il Verb Edit è selezionato, esistono 
una serie di controlli appositi per la configu- 



<asp:EditorZone ID = "EditorZonel" 

runat="server"> 
<ZoneTemplate> 

<asp:AppearanceEditorPart 

ID = "aep" Runat="server" /> 
<asp:BehaviorEditorPart 
ID="bep" 

Runat="server" /> 
<asp:LayoutEditorPart 
ID = "lep" 

Runat="server" /> 
Altri controlli... 
</ZoneTem piate > 



</asp:EditorZone> 



W* «H**p*a «p, ** •**** 



*aw»**fcr«H 






■XltHOOf 



Fig. 4: Le Web Parts attraverso apposite maschere 

Questi marcatori generano le maschere illu- 
strate in Fig. 4. 
Per la precisione 

• AppearanceEditorPart Serve a modificare 
l'altezza, la larghezza, la direzione (oriz- 
zontale o verticale) il titolo, il testo e il 
bordo 

• LayoutEditorPart Serve a spostare le Web 
Parts, come se la pagina fosse in modalità 
Design, è utile perché alcuni browser non 
consentono di spostare le Web Parts trasci- 
nandole con il cursore del mouse 

• PropertyGridEditorPart Utilizzato per pro- 




Fig. 5: Il sito usabile.it è un buon riferimento 



► 36 /Settembre 2006 



http://www.ioprogrammo.it 



Programmare con le Web Parts H T ioProgrammo Web 



grammare le proprietà delle Web Parts svi- 
luppate da noi 
• BehaviorEditorPart È un controllo che 
dovrebbe essere visibile solo agli utenti 
con il ruolo di amministratore dell'appli- 
cazione poiché le modifiche che imposta 
alla Web Parts saranno applicate a tutti gli 
utenti dell'applicazione; si occupa di sele- 
zionare quali Verbs è possibile abilitare. 

Una curiosità: programmando le Web Parts, 
in modalità Edit, ci si imbatte nella non 
meglio definita proprietà Chrome; 
questa proprietà si occupa della grafica del 
bordo che racchiude la Web Parts. 
Nota che la parola Chrome viene utilizzata 
per definire la cornice che racchiude le fine- 
stra delle moderne interfacce utente grafiche. 



•U" 



«5 I e— vi» I mm»*^- 



stato della pagina in maniera tale che sia 

nello stato User, per l'utente Amministratore 
nello stato Shared per tutti gli altri. 

Questa funzionalità è programmata attraver- 
so l'istruzione 

1 Innesca l'evento premendo un bottone 
Protected Sub Toggle_Scope_Button_Click(ByVal 
sender As Object, ByVal e As EventArgs) 
_manager. Persona lization.ToggleScope() 
End Sub 

che funge da interruttore tra lo stato della 
pagina User, ovvero lo stato dedicato 
all'Amministratore a quello Shared, lo stato 
di tutti gli altri utenti. 

Creare un ruolo per gli utenti è indispensabi- 
le per utilizzare il controllo BehaviorEditorPart 
trattato poche righe sopra che, ripeto.si occu- 
pa di selezionare quali voci di menù saranno 
visibili a tutti gli utenti dell'applicazione. 
Il ruolo degli utenti è memorizzato nel data- 
base Aspnetdb.mdf, un database SQL Server 
Express Edition, presente nella cartella 
App_Data e generato automaticamente dal 
.NET Framework allo scopo di conservare gli 
utenti delle nostre applicazioni ed i relativi 
ruoli. 




Fig. 5: Google fa un uso intensivo delle Web Parts 



IL RUOLO 
DEGLI UTENTI 

Ogni applicazione Web moderatamente com- 
plessa ha delle pagine "amministrative" che 
consentono a utenti che godono di particola- 
ri permessi di gestire il sito web: ad esempio 
l'Amministratore di un Forum può cancellare 
alcuni account di utenti non graditi. 
L'utente Amministratore ha il compito di per- 
sonalizzare le Web Parts; Il ruolo di 
Amministratore è programmato nel file 
web.config 

<webParts> 

<personalization> 
<authorization> 
<allow users="*" 

verbs = "enterSharedScope" /> 
</authorization> 
</personalization> 
</webParts> 

Una volta settato quali utenti hanno il ruolo 
di Amministratore è necessario impostare lo 



9_- 

— -«- 



Wc" !— ~,.^ ~z 




Fig. 6: Notate oil riquadro celeste a sinistra 



WEB PARTS. 
E USABILITÀ 

Ogni volta che viene inventato un nuovo 
modo per assemblare una pagina web ecco 
che, a proposito o a sproposito, incomincia- 
no a proliferare siti che riprendono la nuova 
idea. 

Se poi è veramente opportuno implementar- 
la è un altro discorso; 

decidere se le Web Parts sono adeguate al sito 
che stiamo costruendo non è solo una que- 



http://www.ioprogrammo.it 



Settembre 2006/ 37 ► 



ioProgrammo Web T I Programmare con le Web Parts 




w <"• JJ v 




~ : : i : . ■* : 



* \ K - Mtw.it Militi- 

1 | Il nam* 



Sport - tajrrtim h 



F/g. 7: // s/to live.com è un buon esempio d'uso 
delle Web parts 

stione tecnica ma anche una questione di 
usabilità. 

Per chiarire tutto questo abbiamo chiesto 
lumi a Maurizio Boscarol professore di 
Editoria Multimediale all'Università degli 
Studi di Trieste, autore del testo "Ecologia dei 
siti Web" e responsabile del sito usabile.it. 
Per capire se le Web Parts sono usabili e quan- 
do è opportuno utilizzarle è necessario osser- 
vare l'uso che utenti reali fanno di un prodot- 
to per capire le loro esigenze, magari attraver- 
so test di usabilità per osservare direttamente 
le cose che loro stessi, anche se intervistati, 
non sarebbero magari in grado di esprimere. 
Per l'utente l'usabilità delle Web Parts dipen- 
de essenzialmente da come l'utente stesso 
percepisce (o non percepisce) la possibilità di 
utilizzo. 

A monte bisognerebbe capire se le personaliz- 
zazioni consentite sono viste dall'utente 
come un vantaggio o rimangono essenzial- 
mente ignorate. 

Non sempre la presenza di una possibilità tec- 
nica si traduce in un vantaggio percepito. 
È chiaro dunque che le possibilità di uso delle 
WP dipende essenzialmente dalla tipologia di 
utenti e dall'ambiente che si sta creando; ad 
esempio solo pochi fra gli utenti occasionali 
di un sito informativo si prenderanno la briga 




di personalizzarlo: quello che cercano è la 
segnalazione delle novità più recenti, e un'in- 
terfaccia sufficientemente stabile da non 
dover essere reimparata ogni volta, al contra- 
rio, laddove il progetto è rivolto ad una serie 
magari chiusa di hard users, che usa ripetuta- 
mente il prodotto (penso al caso di una intra- 
net, o di siti per utenti registrati, che consen- 
tano un'operatività ampia), allora le WP 
potrebbero trovare una buona applicazione 
In ogni caso, proprio perché la risposta varia 
in base a contesti e a tipi di utenti e di compi- 
ti, il risultato andrebbe sempre preventiva- 
mente testato con utenti reali. 
In sostanza, come ripeto, una possibilità tec- 
nica è utile e proficua solo se inserita in un 
corretto processo di progettazione, che preve- 
da verifiche con utenti. 

Le possibilità funzionali senza una procedura 
di user centred design rischiano spesso di 
provocare più grattacapi agli utenti di quanti 
non ne contribuiscano a risolvere! 



-J. 



Fig. 8: Un esempio d'uso sul sito msn.com 



Fig. 9: Il controllo sugli utenti è molto funzionale 



CONCLUSIONI 

La brevità dell'articolo mi ha costretto ad 
accennare solamente alle molteplici 
funzionalità di questa tecnologia; 
fedele al ritornello della canzone di Elvis 
Presley: "Little less conversation little more 
action" vi informo che, nell'esempio allegato, 
vedrete in azione tutto quanto esposto nel- 
l'articolo ed anche qualcosa in più... 
Partendo da queste righe potrete senz'altro 
iniziare a costruire Web Parts professional- 
mente. La tecnologia è matura e Visual Studio 
contiene una serie di controlli che potranno 
ulteriormente aiutarvi. Il miglior modo per 
comprendere questo articolo è provare prati- 
camente quanto descritto. La pratica 
mostrerà quanto questa tecnica sia efficace. 

Luigi Corrias 



► 38 /Settembre 2006 



http://www.ioprogrammo.it 



DATABASE ▼ H Object Relational Mapping 



DAL LINGUAGGIO SQL 
AGLI OGGETTI 

INDAGHEREMO PIÙ A FONDO NELLE POTENZIALITÀ DEL FRAMEWORK HIBERNATE. 
PRESENTEREMO UN PLUGIN CHE CI PERMETTERÀ DI SVILUPPARE GUI ALL'INTERNO DI 
ECLIPSE. IMPAREREMO COME I DATABASE POSSANO ESSERE TRATTATI COME OGGETTI 




Nel precedente articolo ci siamo occu- 
pati del framework Hibernate associa- 
to ad un RDBMS MySQL. In particola- 
re abbiamo potuto apprezzare come, grazie a 
questo portentoso framework, sia possibile la- 
vorare con un database proprio come se stessimo 
sviluppando una classica applicazione Object 
Oriented. Ottenere tutti questi vantaggi diven- 
ta ancor più agevole se come ambiente di svi- 
luppo si utilizza Eclipse assieme al plugin mes- 
so a disposizione dalla stessa Hibernate Foun- 
dation (reperibile all'indirizzo http://www.hi- 
bernate.org/255.html . 

Per chi si fosse perso la scorsa puntata faccia- 
mo un breve riassunto per focalizzare il punto 
da cui partiremo in questo articolo. 



UHI DATABASE 
AD OGGETTI 

L'esempio da cui siamo partiti è l'implemen- 
tazione di una semplice applicativo finalizzato 
alla gestione dei contenuti presenti nella no- 
stra videoteca domestica. 
Riportiamo quindi "l'analisi dei requisiti" ef- 
fettuata la volta precedente tenendo a mente 
che essa costituisce la base su cui è stato pro- 
gettato l'intero database e di conseguenza in- 
fluirà pesantemente anche sul futuro sviluppo 
del nostro front-end: 

La base di dati deve gestire l'elenco dei video 
in possesso dell'utente. Ogni video è memo- 
rizzato su uno o più supporti (nel caso di co- 
pie di backup) che debbono essere identifica- 
ti da un numero univoco. Ogni video è identi- 
ficato da un titolo e, per ciascuno di esso, pos- 
sono essere specificate ulteriori informazioni 
come la data di uscita, il genere, il regista ed il 
cast di interpreti. Sia per i registi sia per gli in- 
terpreti è necessario specificare nome e co- 
gnome ed eventualmente la loro data di nasci- 
ta. Per quanto riguarda il genere del filmato es- 
so è identificato da un proprio nome (comico, 



drammatico, video clip, etc...). 
Da quanto riportato sopra, in primo luogo, si è 
costruita la base di dati (il nostro back-end), il 
cui script SQL è riportato in allegato al CD. 
Il passo immediatamente seguente è stato pro- 
prio quello di "riportare" il database in oggetti, 

meglio in classi Java, in modo tale da avere, 
appunto, oggetti che mappassero la tabelle e 
le relazioni presenti nel back-end. Tale opera- 
zione non è risultata poi granché onerosa gra- 
zie all'utilizzo del plugin riportato all'inizio del- 
l'articolo. In particolare gli strumenti di rever- 
se engeenering messi a disposizione dal plu- 
gin di Hibernate ci ha permesso di avere un set 
di classi che ricalcano la struttura della base di 
dati su cui abbiamo impostato tutta l'applica- 
zione. 

Il diagramma UML di figura 1 riporta la struttura 
ottenuta (per motivi di brevità si riporta solamente 
tale rappresentazione grafica senza dilungarsi 
in ulteriori considerazioni fatte nell'articolo 
precedente). Il plugin in questione ci ha inoltre 
permesso di generare gli opportuni file di con- 
figurazione che permettono al framework Hi- 
bernate di comunicare con il database sotto- 
stante. 

Ci eravamo infine lasciati con un paio di esem- 
pi che illustravano come, arrivati a questo pun- 
to, fosse molto semplice persistere i nostri og- 
getti sul relativo database. Sarà proprio da qui 
che ricominceremo. 

Per essere più precisi divideremo questo arti- 
colo in due macro-sezioni: 

1 prenderemo una maggiore dimestichezza 
con il framework di Hibernate implemen- 
tando una serie di HQL Procedures (capire- 
mo poi meglio di cosa si tratti) da invocare al- 
l'occorrenza da un'interfaccia grafica. 

2 implementeremo, per mezzo di un altro plu- 
gin di Eclipse, una serie di forni che faran- 
no la nostra applicazione veramente user- 
friendly 



> 40 /Settembre 2006 



http://www.ioprogrammo.it 



Object Relational Mapping ■ T DATABASE 



moni PROPRIO SQL 
MA HQL 

Come abbiamo ripetuto già più volte, Hiberna- 
te è sostanzialmente un framework logico che si 
frappone tra lo strato applicativo e quello del 
DB (vedi figura 2) . È naturale quindi che, dal la- 
to applicativo, non andremo ad utilizzare di- 
rettamente dei comandi SQL, sia perché ciò ren- 
derebbe inutile o superfluo l'utilizzo di tale fra- 
mework, sia perché dobbiamo sempre tenere a 
mente che stiamo sviluppando in ottica Object 
Oriented e quindi non abbiamo più a che fare con 
tabelle e relazioni (fortunatamente!) ma con 
classi. D'altro canto è altrettanto logico che per 
"maneggiare" questo tipo di oggetti si utilizzerà 
qualcosa di molto vicino allo standard SQL. 
Ciò di cui stiamo parlando è proprio HQL che sta 
proprio per Hibernate Query Language. 
Senza dilungarci in tediose discussioni su qua- 
li siano le differenze sostanziali fra questi due pa- 
radigmi mettiamo subito in campo un paio di 
esempi utili per chiarirci le idee al riguardo. 
Per prima cosa riproponiamo la classe Hiber- 
nateUtil alla quale ci appoggeremo spesso: 

public class HibernateUtil { 



private static final SessionFactory 



sessionFactory; 



Cd ed = newCdQ; 



cd.setNumero(n); 



session.save(cd); 



static { 



} 



Quello che va sottolineato in questo caso è che l'oggetto 
Session ci è passato dal chiamante e quindi ci dob- 
biamo solamente occupare di scrivere le nostre azio- 
ni (nello specifico un salvataggio del ed per mezzo del 
metodo save) sull'oggetto Session. Quindi è bene te- 
ner presente che l'oggetto in questione non è stato 
ancora salvato sul database. 

Se invece vogliamo creare una procedura one-shot, 
cioè una procedura che renda subito effettive le no- 
stre azioni sul DB, dovremmo fornire un overload di ta- 
le metodo: 

public void insert(int n) { 

Cd ed = new Cd(); 

cd.setNumero(n); 

Session session = HibernateUtil. gè 
SessionFactory().getCurrentSession(); 

session. beginTransaction(); 

session. save(cd); 

session. getTransaction(). commit() ; 
} 



sessionFactory = new Configuration() 

.configure().buildSessionFactory(); 
_> 

public static SessionFactory getSessionFactory() 

{_ 

return sessionFactory; 



} 



In sostanza questa classe ci permette di lavorare con 
un'unica session factory indipendentemente dal pun- 
to in cui viene invocato; in altre parole non abbiamo 
fatto altro che implementare un Singleton. 
Quello che ora ci piacerebbe realizzare è una serie di 
procedure sulla falsa riga di quelle che sono le Stored 
Procedures implementabili ormai su quasi tutti i mo- 
derni RDBMS. 

Partiamo dalla classe più semplice: CD. 
Come potete notare, dal diagramma in figura 1 , la clas- 
se CD ha un solo attributo di tipo int che identifica in 
maniera univoca il supporto indicato. Se volessimo 
creare una procedura che si occupi della persistenza 
di tale classe basterà: 

public class CDProcedures { 



In questo caso tutta la transazione viene gestita al- 
l'interno del metodo stesso, dal punto del begin fino 
al punto di commit. 

Fin qui però abbiamo visto ben poco di qualcosa che 
somigliasse al buon vecchio SQL. Vediamo quindi ora 
una procedura che dal database "tiri su" tutti i CD a 
nostra disposizione e ce li esponga come un array del- 
la classe CD. 

Il codice in questo caso è un po' più complesso del 
precedente. 

public static Cd[] getAIIQ throws HibernateException 

{_ 

Session s = 
HibernateUtil. getSessionFactory() 
.getCurrentSession(); 
try { 



s.beginTransactionQ; 



List res = 
s.createQuery("from wrap.Cd") 



.list() ; 



Cd[] out = new 

Cd[res.size()]; 



out=(Cd[])res.toArray(out); 



s.close(); 



return out; 



} catch (HibernateException e) 



COSA VUOL 
DIRE WYSIWYG 

L'acronimo WYSIWYG 
sta per What You See Is 
What You Get (quello 
che vedi è quello che 
hai) ed indica tutti 
quegli editor/IDE in cui 
si può ottenere una 
rappresentazione 
grafica immediata di 
ciò che si sta 
sviluppando. 



public void insert(int n, Session session){ 



{ 



http://www.ioprogrammo.it 



Settembre 2006/ 41 ► 



DATABASE T il Object Relational Mapping 




ALTRI PLUCIIU 
DI ECLIPSE 

La Eclipse 

Foundation ha 

sviluppato un 

plugin per la 

generazione di GUI 

di nome Visual 

Editor Project 

(http://www, eclipse, or 

q/vep/WebContent/mai 

n.php) che però, a 

mio parere, risulta 

ancora un po' più 

pesante di Jigloo 



Applicazione 



H ibernato 
Frameworfc 



Iftrttnlktnikxw 



ti 



Driver JDBC 




Database (MySQL) 



Fig. 2: Architettura complessiva di un'applicazione 
basata su Hibernate 

throw e; 
} 
} 
Cominciamo con il concentrarci sulla query. Il 
comando inviato al framework from wrap.Cd. 
Questa sintassi somiglia molto alla classica query 
SQL: SELECT * FROM Cd; 
Visto che però abbiamo a che fare con classi e non 
con campi la prima parte di quella query, per 
adesso, risulterebbe superflua. Va inoltre nota- 
to anche come sia sempre necessario specifi- 
care il nome esteso della classe, cioè compreso 
il nome del package (nel nostro caso wrap). 
Una volta creata la query si trasforma il risulta- 
to dell'interrogazione mediante il metodo list() 
che restituisce appunto un oggetto di tipo List. 
Poiché tale classe contiene generici Object dob- 
biamo effettuare un cast dinamico e contem- 
poraneamente estrarre un array Cd. La solu- 
zione qui adottata risulta la più efficiente sia a 



- Mv* hn* irmnw.HY* Ethpw SOk 


Efc fc* RttMK* &0«* H*"9* *<M«.li Pwjttl gun ift-mJ™ Utfc 

*:* u a 1 A M »• O» <4- r «* £ 9 9* 4 «fj hi fi 1 • :.•«>.*•*• 


B^B 


- Packagi Capta,. & *i "C 

* * * 


' HifatmatlMiavi ,' C DFiKtdim java ■ B *j * 3 
^M f wwivwiwi McraLomponenn Menu Ctncom Lavai 




* HitmMtAppCD 


£5 

■ 


■Ji«a > 


: ' E vira cwnpcfwmi 

i' hcm-M-c ujI * ran peroni i. 


qui 

*■ • -ili -■,r.ii.ii---ì i.ì. ,i 

1 | OuUtÉ.|ava 
fr | IwwiCD.un* 
b ,L IrtwrrFam |abU 

^ mi 

: uhi 

* it-uht.iftLlPiWrfunj* 

► .fr ifULtHurt 

* Wtìemait.crfl.Mnl 
Kurt ptìprtì** 






Inveri nei 

a : 




B 

•pn java. ani. BortìtrLayouT: 

* Thi« Mft «»« «dil-ad ni g»Mrit*d ukìiir C ToudCardMi ' t 1 

- Builder, «hiLh U Inr li*r nuti ivn«rail use. Il Jl^J J 

' EOHHffcially fi*, by a eorpOTicìan. coopinv or bus in* b a (or , 

> 




PMNm 


JjvjdDV DntJiJi™ Contar- C Uà Hnai^ ^irtli ■ CUI Frcp-rim H ™B 


* - jRFVMi-nilAi^llA-^ GUlPnùfH 


*h« [ Ai; JF rjfiw ] * 


► * iws*-toiin«io»i«*ò.] L PrùpBrt#: 


Vjft* i W*t Vjìu* F.,r*W 


xntnrljirfiH -^khm- 


► » nrilr^.7.Gfc|.j«r..r1«m/9> , ^j. 


» CwvtiraHirc Ho Conuram* '■ C«r 


► « tMMMldP itwmer^Jar: » 


qround [??D. ?3& 211 '" » layout JfiixJPanrf) » fai! 


—*•<«"■ —~- 


r^rtìff^Ti, min. f » WMUNc S«Mfllm«t 1.1 



livello di performance sia a livello di pulizia di 
codice; eventuali cicli for o simili appesanti- 
rebbero solamente il tutto. Ora che abbiamo 
acquisito un po' più di confidenza con il fra- 



CD 

Select a wizard 




HDJInremalFrame 

MJ Panel 

il Switia Mairi Aoolitzation 



' Next > | Cancel 



Fig. 4: Prospective generata da Jigloo 



Fig. 3: Schermata dì creazione della Form. 

mework Hibernate introduciamo un altro plu- 
gin per Eclipse che ci permette di realizzare del- 
le interfacce grafiche in maniera relativamente 
semplice. 



COSTRUIRE GUI 

COIU ECLIPSE? ORA 

E POSSIBILE COI\l JIGLOO 

Uno dei punti deboli dell'IDE Eclipse, per lo 
meno nei confronti del suo diretto concorren- 
te NetBeans della SUN, è stato proprio quello 
di un supporto WYSIWYG per lo sviluppo di in- 
terfacce grafiche. Fortunatamente l'architettu- 
ra di Eclipse è nata per essere "scalata", cioè per 
essere ampliata mediante l'uso di opportuni 
plugin a seconda delle esigenze dello sviluppa- 
tore. Il plugin che andremo ad utilizzare si chia- 
ma Jigloo ed è disponibile all'indirizzo 
http://www.cloudgarden.com/jigloo/. 
Dopo averlo installato, vediamo subito di met- 
terlo all'opera per creare il Jframe principale 
per la nostra applicazione. Prima di tutto, do- 
po aver creato un nuovo package dove mettere 
tutti i componenti GUI, scegliere File ->New - 
> Other. A questo punto, se l'installazione del 
plugin è andata a buon fine, selezionare GUI 
Forms e la sotto-cartella SWING (visto che saranno 
questo tipo di librerie che andremo ad utilizza- 
re). All'interno di tale sotto cartella selezionare 
infine JFrame ed immettere il nome per tal clas- 
se. Jigloo vi aprirà così una nuova prospctive si- 
mile a quella mostrata in figura 4. Naturalmen- 
te sarebbe troppo lungo ed anche noioso di- 
lungarsi su ogni aspetto di questo plugin od 



»> 42 /Settembre 2006 



http://www.ioprogrammo.it 



Object Relational Mapping ■ T DATABASE 



ogni componente dell'interfaccia che stiamo 
realizzando. Inoltre Jigloo si rivela un plugin ab- 
bastanza intuitivo per chiunque conosca un po' 
di Swing; per questo motivo elencheremo sem- 
plicemente tutti i componenti grafici che an- 
dremo ad assemblare insieme. Come avrete no- 
tato, Jigloo divide la schermata centrale a metà: 
la parte superiore vi mette a disposizione l'am- 
biente drug & drop per "sistemare" i vari com- 
ponenti, mente quella inferiore riporta il codi- 
ce generato da ogni vostra azione effettuata nel- 
la metà superiore. Il nostro JFrame deve esse- 
re composto da due JPannel affiancati orizzon- 
talmente: il primo conterrà un menu che ci per- 
metterà di aprire nuove form ed una JTable do- 
ve visualizzeremo i risultati delle nostre ricerche. 
Tali ricerche sono rese possibili grazie al se- 
condo JPannel in cui sono presenti, oltre al bot- 
tone Cerca, il JField per il Titolo del video e due 
JComboBox per il numero di CD ed il Genere. 
Naturalmente a questi campi abbiamo affiancato 
le loro rispettive JLabel. Una volta composta la 
struttura sopra descritta e riportata in figura 5, 
bisogna mettere mano al codice per imple- 
mentare tutte quella funzionalità che sarebbe 
impossibile dal lato WYSIWYG. La prima cosa 
da fare è definire il listner per il bottone Cerca, 
tale listner sarà la classe NewFrame stessa: 

public class NewJFrame extends javax. swing. JFrame 
implements MouseListener,ActionListener { 



} 



jButtonCercaFilm.addMouseListener(this); 



} 



Occupiamoci poi della JTable. Questa classe ha bi- 
sogno di incapsulare un oggetto TableModel che 
gestisca i contenuti della Table. In altre parole bi- 
sogna implementare la classe astratta sopra citata 
nel seguente modo: 

public class FrontTable extends AbstractTableModel { 

private Film[] films; 

public FrontTable(Film[] films){ 

this.films=new Film[films.length]; 

System.arraycopy(films,0,this.films,0,films.length); 



public int getRowCountQ { 

return this. films. length; 



public int getColumnCount() { 
return 1; 



public Object getValueAt(int rowlndex, int 

columnlndex) { 



return films[row!ndex]; 



); 



jTableOut = new JTableQ; 




} 



I metodi che sono stati riportati sono quelli che 
sono definiti come astratti nella classe base e i 
loro nomi sono già autoesplicativi. La conside- 
razione importante che in questo caso va fatta 
è quella di prestare attenzione a come sono in- 
capsulati i dati. Infatti, come noterete, un array 
di Film viene copiato al momento dell'invoca- 
zione del costruttore ed in base ad esso vengo ef- 
fettuate le operazioni sulla tabella stessa. Al 
momento dell'inizializzazione creiamo un Front- 
Table con un oggetto Film vuoto in modo tale 
da far apparire la JTable vuota al momento del- 
l' avvio. 

TableModel jTableOutModel = new FrontTable(new 
Film[]{ 

new Film() 

} 



jScrollPanel.setViewportView(jTableOut); 
jTableOut.setModel(jTableOutModel); 

Per quel che riguarda invece le ComboBox dobbia- 
mo caricare da DB rispettivamente tutti i generi ed 
i CD presenti. Ad esempio per i CD tal compito vie- 
ne svolto dal seguente metodo: (anche per i generi 



EJ* E*i Rcfjcipr 5™tc H">9* s*#iii e'***' 6"» \K"*» H* 

-• M ■ - A * ¥• O- *■ ■•' A » (** * «' .«{J I .". 

i HbmMiUé.i*ti ■' COPiK«dunj»rfl ' rplmPt«*d4#M.|i*a ' CwMMFroeidmijK. 



" 



i " 1 " i J 3 ■ B 




i.Mj.i.u„-ijjin'miiBw.rrT 



MtpTtirZmt&^i 



Titolo 
CO 



C 



re 



IfFmll ■ JPmrt. Gwtflafl . Center 
_j Yphtj FJnT jBunuiT tic jFilrr, - JBi I 

■TW |Ub*U: - JUbtL AbMhM 

Twrtmr- |l.ihrll JLattri fiir.ckÈt 
I "ir^lF'K.-Ulittfc JTcn*icW, Bjìi] 
! pComtaBnCO - JCombeftn. Bum | 



MUfaM KJtM 

frtfunTrj.-oruilP.aJti [| 



Wr-jMc S*rwrt linai 199 ! 1 



Fig. 5: Layout della classe NewJFrame.java dove sono anche elencati tutti I compo- 
nenti. 



http://www.ioprogrammo.it 



Settembre 2006/ 43 ► 



DATABASE T H Object Relational Mapping 




metodo è pressoché analogo) 



private Object[] getCD(){ 


try{ 




Cd[] ed 
Object[] 


=CDProcedures 
obj = new 


getAIIO; 






Object[cd. 


ength+1]; 






obj[0] = new E 


mptyQ; 


System 


arraycopy(cd,0,obj. 


l,cd.length); 




return obj; 




} catch 


(HibernateException e) { 


return newString[]{""}; 


} 


} 



Oltre ad invocare una procedura illustrata preceden- 
temente, abbiamo aggiunto un oggetto empty all'ini- 
zio dell'array così che l'utente possa effettuare la ri- 
cerca indipendentemente dal CD. In altre parole se il 
numero di CD non è specificato la ricerca verrà effet- 
tuata su tutti i supporti di memorizzazione. Lo stesso 
vale per la classe Genere. Il caricamento sulla ICom- 
boBox avviene in questa maniera: 

ComboBoxModel jComboBoxCDModel = new Default 

ComboBoxModel(getCD()); 
jComboBoxCD = new JComboBox(); 

ComboBoxCD.setModel(jComboBoxCDModel); 

A questo punto non ci rimane che scrivere il codice 
necessario ad effettuare una ricerca (che passi natu- 
ralmente per il framework Hibernate) dei contenuti 
multimediali che desideriamo. Tale codice verrà atti- 
vato nel momento in cui l'utente premerà il bottone Cer- 
ca, per cui si ha: 

public void mouseClicked(MouseEvent e) { 



if(e.getSource()==jButtonCerc 



FilmX 



Film[] films = FilmProc 
dures.getFilms(jTextFieldTitolo.getText(),true); 



jTableOut.setModel( 
new FrontTable(films) 

); 



} 
Tutta la logica è quindi contenuta nel metodo statico 
FilmProcedures.getFilms che andiamo immediata- 
mente ad analizzare: 

public static Film[] getFilms(String titolo, 

boolean lasco) 

{ 

String where; 
if(lasco) 

where ="f.titolo like 

, %"+titolo+"%'"; 
else 

where ="f. titolo ="+titolo; 
String query = "from wrap.Film f 

where "+where; 
Session s = HibernateUtil. 
getSessionFactory().getCurrentSession(); 
s.beginTransactionQ; 



List list = s.createQuery 



(query). Iist(); 



s.closeQ; 



Film[] films = new Film[list.size()]; 



films=(Film[])list.toArray(films); 



return films; 



} 



È stato definito un flag che indica se la ricerca va ef- 
fettuata sulla frase esatta o basta che il titolo con- 
tenga la frase come sotto-stringa. Infatti la clauso- 
la where viene costruita in questo modo: 



if(lasco) 


where = 


'f.titolo 


like 


'% 


'+titolo+ 


%" 


; 


else 








wh 


Bre = 


= "f.titolo 


'-l-titolo; 



dopodiché si crea la query vera e propria: 

String query = "from wrap.Film f where 

"+where; 

La parte restante del codice non presenta nulla di 
nuovo rispetto alle procedure già presentate. Lascio 
a voi, se volete, creare nuove procedure che tengano 
in considerazione ulteriori classi del package wrap. 



INSTALLAZIONE DI JICLOO 



Per installare Jigloo basta 
selezionare dal menu di Eclipse 
Help->Software Updates->Find 
and Instali e selezionare search 
for new features to 
instali. Cliccare poi su New 
Remote Site ed immettere 
l'URL 
http://cloudgarden1.com/updat 



e-site, a questo punto sarà 
Eclipse stessa a scegliere la 
versione giusta per il vostro 
IDE. Per chi lavora su macchine 
POSIX ricordarsi che queste 
operazioni vanno eseguite 
dallo stesso utente che ha 
installato Eclipse (tipicamente 
il SU). 



CONCLUSIONI 

Nell'arco di questi due articoli abbiamo avuto mo- 
do di apprezzare una parte delle potenzialità che ci 
vengono messe a disposizione da Hibernate, Ecli- 
pse ed i suoi plugin, ed il mondo lava in generale. 
Tutto naturalmente in piena filosofia Open Sour- 
ce si intende! 

Andrea Galeazzi 



»> 44 /Settembre 2006 



http://www.ioprogrammo.it 



DATABASE ▼ il Massimo riutilizzo minimo sforzo 



CUSTOM DATA 
PROVIDER CON .NET 

IMPLEMENTIAMO UN COMPONENTE INTERMEDIO CHE CONSENTE DI ACCEDERE A 
QUALUNQUE TIPO DI DATO UTILIZZANDO GLI STESSI METODI E INTERFACCE E VARIANDO 
SOLO POCHI PARAMETRI. SFRUTTEREMO IL NOSTRO HD COME UN DATABASE 




fi 




REQUISITI 



Conoscenze richieste 



conoscenze medie 
I diC# 



NET Framework 2.0, 
Microsoft Visual Studio 
.NET 2005 



^M^à^M 



Tempo di realizzazione 



00 



Un .NET data provider è un insieme di 
classi utilizzato solitamente per con- 
nettersi a un database, eseguire comandi 
SQL su di esso e leggere i risultati di tali coman- 
di. Esistono dunque provider specifici per i da- 
tabase più supportati, come Access ed SQL Ser- 
ver, e provider forniti eventualmente da terze 
parti, come ad esempio quelli che permettono l'ac- 
cesso a MySql o PostgreSql. Un data provider è dun- 
que uno strato di software che permette ad un'ap- 
plicazione di interagire con dei database, stra- 
to che costituisce un'interfaccia comune per ri- 
cavare dei dati da utilizzare poi per diversi sco- 
pi, ad esempio per visualizzare dei report, o per 
fare dei calcoli su di essi. Questa interfaccia è 
comune a tutti i provider, dunque, qualunque 
sia il database sottostante, è possibile utilizzare 
le stesse procedure per lavorare con essi. Tutto 
ciò è possibile grazie all'architettura ad inter- 
facce e classi astratte, con cui tutti i provider so- 
no implementati. Il bello dell'architettura è che 
non è limitata all'accesso ad un database com- 
merciale, ma può essere sfruttata anche per ac- 
cedere a fonti di dati personalizzate, ad esem- 
pio ad un database personale, al registro di si- 
stema, o ai tipi di un assembly, o a qualunque 
tipo di dato si possa immaginare. In questo ar- 
ticolo vedremo quali sono le classi e le interfac- 
ce che un custom provider deve esporre, e le im- 
plementeremo per creare un minimo provider 
di accesso al file system, per effettuare delle ri- 
cerche come se si trattasse di una sorta di data- 
base SQL. 



L'ARCHITETTURA 
DI UHI PROVIDER 

Un .NET Data Provider è costituito in genere da 
quattro classi principali, che implementano al- 
trettante interfacce e che collaborano fra di esse 
in maniera praticamente standard. 
La classe Connection è una classe richiesta anche 
se il provider non dovrà connettersi ad un data- 



base relazionale. Le altre classi utilizzano una Con- 
nection per connettersi a qualsiasi genere di dati. 
Ad esempio i DataAdapter usano una connessio- 
ne per riempire un DataSet. La classe Command rap- 
presenta un comando da inviare ad una sorgente 
dati, per un database, ad esempio, un Command 
sarà un classico Insert, Update e così via, oppure 
Select se è un comando che restituisce dei record. 
La classe DataReader si occupa di processare i ri- 
sultati di un Command in maniera sequenziale, 
partendo dal primo fino all'ultimo in maniera 
forward-only. Inoltre per ogni riga consente di leg- 
gere diversi attributi, ad esempio per un database 
consentirà di leggere i vari campi di un record. 
La classe DataAdapter riempie un DataSet con i 
risultati di un Command, ed è utilizzata per ri- 
mandare indietro alla sorgente dati, aggiornan- 
dola, le eventuali modifiche fatte sul DataSet. 
Tali classi implementano delle interfacce anch'esse 
naturalmente standard, dunque avremo un'inter- 
faccia IDbConnection, una IDbCommand, la IDb- 
DataAdapter, e la IDataReader. Esistono poi altre 
classi a contorno, più specialistiche, che servono 
ad esempio per aggiungere il supporto alle tran- 
sazioni, dei parametri ai comandi, o anche delle 
classi di eccezioni personalizzate, 



SCRIVERE Ul\l PROVIDER 

Per mostrare l'implementazione di un custom pro- 
vider, che svolga dei compiti di ricerca sul file sy- 
stem, creeremo alcune delle classi standard viste, 
in particolare una che rappresenti la connessione 
ad una directory dell'hard disk, una per i coman- 
di di ricerca da inviare, ed un DataReader per leg- 
gere sequenzialmente i risultati. Non ha senso in 
questo caso un DataAdapter, in quanto vogliamo 
solo ricavare dei dati in lettura. 
Non tutti i metodi e le proprietà delle interfacce 
saranno implementate, in quanto non avrebbero 
alcune volte utilità, ed in quanto non abbiamo lo 
scopo di creare un provider ADO.NET completo 
sotto tutti i punti di vista. Chi vorrà, comunque, 



»> 46 /Settembre 2006 



http://www.ioprogrammo.it 



Massimo riutilizzo minimo sforzo I ▼ DATABASE 



potrà estendere il provider, con nuovi comandi ad 
esempio, o implementando le funzioni assenti. 



IL FILESYSTEMPROVIDER 

Il provider che verrà implementato nel corso dell'ar- 
ticolo ha lo scopo di consentire la ricerca di file e directory 
sul file system, a partire da una certa directory di par- 
tenza, utilizzando dei comandi simil-SQL. 
Ad esempio per farsi restituire tutte le sotto-directory 
di una data cartella, insieme ad informazioni, come 
la data di creazione ed il numero di file contenuti in 
esse potremo utilizzare un comando simile a "SELECT 
dir", per ottenere invece solo i file scriveremo "SELECT 
files", o "SELECT *" per entrambi i tipi. Inoltre imple- 
menteremo anche una sorta di filtro, per ricercare so- 
lo determinati file o cartelle, con comandi ad esem- 
pio del tipo "SELECT file WHERE Name LIKE 'a*'" per 
ottenere i file che iniziano per 'a'. 
La figura seguente mostra il diagramma delle tre clas- 
si che si andrà ad implementare. 



per conoscere i parametri con cui connettersi ad un da- 
tabase, in questo caso l'unico parametro è percorso 
della directory su file system, dal quale iniziare la ricerca. 
Quindi la stringa di connessione per una FileSystem- 
Connection sarà ad esempio scritta nel formato: 

path="C:\" 

Da tale stringa la classe ricaverà il percorso, memo- 
rizzandolo all'interno del campo database. 

public class FileSystemConnection:IDbConnection 

{ 

private Directorylnfo m_directoryInfo; 
private string database = ""; 
private string connectionString = ""; 
private ConnectionState state = 

ConnectionState.Closed; 
public FileSystemConnection() 



} 

public FileSystemConnection(string connString) 




FILESYSTEMCONNECTION 

La prima classe da creare è la FileSystemConnection, 
che implementerà l'interfaccia IDBConnection. Seb- 
bene l'esempio in questione non abbia bisogno di un 
concetto analogo a quello di connessione ad un da- 
tabase, è comunque necessario implementare la clas- 
se, in quanto le altre, ad esempio Command, utilizza- 
no le funzionalità di una IDbConnection. 





Fig. 1: diagramma delle classi del FileSystemProvider 

La classe FileSystemConnection è mostrata qui di se- 
guito. Alcuni metodi di IDBConnection sono dei sem- 
plici stub vuoti che generano un'eccezione NotSup- 
portedException nei casi in cui il metodo non è im- 
plementato, perché nel caso di una "connessione" al 
file system, non servirebbe. 
Una connessione utilizza normalmente una stringa 



ConnectionString = connString; 



} 



#region IDbConnection Members 

public IDbTransaction BeginTransaction(Isolatio 

Level il) 
{ throw new NotSupportedException("The 

method or operation is not implemented."); } 
public IDbTransaction BeginTransaction() 
{ throw new NotSupportedException("The 

method or operation is not implemented."); } 
public void ChangeDatabase 

(string databaseName) 



{ 



database = databaseName; 

} 

public void Close() 

{ 



database = nuli; 



m_directoryInfo = nuli; 



} 

public Directorylnfo Directorylnfo 



{ 



get 



return m_directoryInfo; 



public string ConnectionString 



get 



return connectionString; 



set 



http://www.ioprogrammo.it 



Settembre 2006/ 47 ► 



DATABASE T I Massimo riutilizzo minimo sforzo 




connectionString=value; 



if (connectionString.StartsWith("path=")) 



database = connectionString. 



Substring(5); 



} 



public int ConnectionTimeout 



{ 



get { return 0; } 



} 



public IDbCommand CreateCommandQ 



{ 



IDbCommand command = 

(IDbCommand)(new FileSystemCommand()); 



command. Connection = this; 



return command; 



} 



public string Database 



{ 



get { return database; } 



public void OpenQ 



{ 



if (connectionString == nuli || connectio 

String.Length ==0) 



{ 



throw new ArgumentException("Connection 

string non inizializzata"); 



} 



if (Directory.Exists(database)) 



{ 



m_directoryInfo = new Directorylnfo 



(database); 



this. state = ConnectionState.Open; 



else 



throw new FileSystemException 



("Directory '" + m_directoryInfo + '" not found.' 



} 



} 



public ConnectionState State 



{ 



get 



} 



Il primo metodo invocato su di una Connection do- 
po la sua costruzione, è il metodo Open, che serve nel 
nostro caso a ricavare le informazioni sul "database" tra- 
mite un oggetto Directorylnfo, naturalmente dopo 
aver verificato che il percorso indicato dalla stringa di 
connessione sia valido ed esistente. 
Nel caso in cui la ConnectionString sia valida, e dun- 
que l'apertura può andare a buon fine, il Connec- 
tionState sarà impostato ad Open. 
Il metodo CreateCommand inoltre permette di crea- 
re un FileSystemCommand, illustrato nel prossimo 
paragrafo, a partire da una FileSystemConnection. 



IMPARTIRE COMANDI CON 
FILESYSTEMCOMMAND 

La classe FileSystemCommand deriva da IDbCom- 
mand, e rappresenta dunque un comando da impar- 
tire in genere ad un database, ed in questo caso dun- 
que un comando di ricerca su file system. 
La struttura generale è la seguente: 

public class FileSystemCommandiIDbCommand 

{ 

private FileSystemConnection m_connection; 

private string m_commandText; 

private CommandType m_commandType; 



} 



Si hanno dunque una FileSystemConnection, creata 
ed aperta come nel precedente paragrafo, il coman- 
do vero e proprio, ed il tipo di comando, che in questo 
esempio sarà sempre un CommandType.Text, in quan- 
to non sono previste tabelle o stored procedure. Un 
tentativo di usare tali tipi genererà un'eccezione: 

public CommandType CommandType 

{ 

get 

{ 

return m_commandType; 



return state; 



} 



#endregion 



#region IDisposable Members 



public void Dispose() 



{ 



if(this.state==ConnectionState.Open) 



CloseQ; 



connectionString = nuli 



} 



#endregion 



set 



{ 



if (value != CommandType.Text) 



throw new 
ArgumentException("L'argomento non è valido.", "value"); 



m_commandType = value; 



} 



} 



La modalità di lettura dei risultati di un comando è 
quella sequenziale, realizzata tramite un FileSystem- 
Reader. Per ottenere un simile oggetto viene invocato 



> 48 /Settembre 2006 



http://www.ioprogrammo.it 



Massimo riutilizzo minimo sforzo I ▼ DATABASE 



il metodo ExecuteReader, che verifica l'apertura del- 
la connessione e quindi costruisce un FileSystem- 
Reader. 

public IDataReader ExecuteReader() 

{ 

// Verifica che la connessione esiste ed è aperta 
if (m_connection == nuli ) 



{ 



throw new ArgumentNullException 

("La connessione non esiste"); 



} 



else if( m_connection. State 



ConnectionState.Open) 



throw new InvalidOperationException 

("La connessione deve essere prima aperta"); 
FileSystemDataReader reader = new 

FileSystemDataReader((FileSystemConnection) 
m_connection, this); 



return reader; 



LEGGERE I DATI 

COI\l FILESYSTEMREADER 

La classe FileSystemReader costituisce il cuore del 
provider, in quanto implementa le parti sostanziali 
che effettuano la ricerca e che permettono di scorre- 
re e leggere i risultati ottenuti. Si vuole dare la possibilità 
di ricercare file, directory, o entrambi contempora- 
neamente. Dunque si avrà bisogno di tre differenti 
campi in cui si manterranno i risultati: 



private FileInfo[] m_files; 



private DirectoryInfo[] m_directories; 



private FileSystemInfo[] m_fileSystemInfos; 

La modalità di lettura sarà determinata e mantenuta 
da un campo del tipo enumerativo ReadMode: 

private enum ReadMode 

{ 

Directory, 

File, 

Ali 

} 

private ReadMode m_readMode; 

Ogni tipologia, inoltre, avrà differenti attributi leggibili, 
che vengono definiti in tre array di stringhe corri- 
spondenti alle tipologie di oggetti: 



private String[] m_dirFields = { "Type" 

"Files 


,"Name", 

, "CreationTime"}; 


private String[] m_fileFields = { "Type" 

"Size" 


"Name", 
"CreationTime" }; 


private string[] m_allFields= {"Type", " 


Marne", 



"DirSize_Or_Files#", "CreationTime" }; 

Altri campi poi serviranno ad esempio a mantenere 
numero di record ottenuti, il puntatore al record at- 
tuale quando si procederà alla lettura sequenziale, ed 
il record stesso, che data la natura eterogenea di essi, 
sarà un array di object: 

private object[] m_row = new object[4]; 
private int m_cursor = 0; 
private int m_recordNumber; 

Il costruttore della classe FileSystemReader, pren- 
dendo in ingresso una FileSystemConnection ed un 
FileSystemCommand 

public FileSystemDataReader(FileSystemConnection 

connection, FileSystemCommand command) 

T~ 

m_connection = connection; 
m_startDirectory = connection. Directorylnfo; 
m_cursor = 0; 
string cmdLower = 

command. CommandText.ToLower(); 




// cosa ricercare? 



if ( cmdLower== "select *") 



{ 



m_readMode = ReadMode. Ali; 



m_fileSystemInfos = m_startDirectory.Ge 

FileSystemInfos(); 



m recordNumber : 



m_fileSystemInfos.Length; 



} 



else if (cmdLower == "select files") 



{ 



m_readMode = ReadMode. File; 



m_files = m_startDirectory.GetFiles(); 
m_recordNumber = m_files.Length; 



} 



else if (cmdLower == "select dir") 



{ 



m_readMode = ReadMode. Directory; 



m_directories = m_startDirectory. 

GetDirectories(); 
m_recordNumber = m_directories.Length; 



} 



else if (cmdLower.StartsWith("select *") 
&& cmdLower.IndexOf(" where name like 



")>7) 



string filter=cmdLower.Substring(cm 

Lower.IndexOf(""')+l); 



if(!filter.EndsWith('"")) 



throw new ArgumentException("Errore di 
sintassi nel filtro del comando \"" + cmdLower+"\""); 
filter=filter.Substring(0,filter.Length-l); 



m_readMode = ReadMode. Ali; 



m_fileSystemInfos = m_startDirectory.Ge 



http://www.ioprogrammo.it 



Settembre 2006/ 49 ► 



DATABASE T il Massimo riutilizzo minimo sforzo 




FileSystemlnfos(filter); 


} 


m_ 


_recordNumber = mJlleSystemlnfos.Length; 


el 


se 


f (command.CommandText.ToLower() = = 

"select files") 


{ 




m_ 


_readMode = ReadMode.File; 




m_ 


_files = m_startDirectory.GetFiles(); 




m_ 


_recordNumber = m_files.Length; 


} 


else if (command.CommandText.ToLower() = = 

"select dir") 


{ 




m_ 


_readMode = ReadMode. Directory; 




m_ 


_directories = m_startDirectory. 

GetDirectories(); 




m_ 


_recordNumber = m_directories.Length; 


} 


else 


{ 




th 


"ow new ArgumentException("Errore di 




si 


ntassi nel comando \"" + command.Command 


Text+"\""); 


} 


m 


JsClosed = false; 


} 



m_row[l] = 

m_fileSystemInfos[m_cursor].Name; 
m_row[3] = 
m_fileSystemInfos[m_cursor]. CreationTime; 
if (Directory.Exists(m_fileSyste 

mInfos[m_cursor].FullName)) 

{ 

m_row[0] = "dir"; 

m_row[2] = new DirectoryInfo(m_file 
SystemInfos[m_cursor].FullName).GetFiles().Length; 



Il comando da eseguire è contenuto nella proprietà 
CommandText dell'oggetto command, ed è dunque 
con uno switch che si può distinguere quale tipo di 
oggetti ricercare ed interpretare il comando stesso ed 
i suoi eventuali filtri. Il simil-sql utilizzato in questo 
esempio permette solo operazioni di ricerca, quindi si 
è utilizzata una keyword select, con la possibilità di ri- 
cercare solo file, con select files, oppure solo directory 
con select dir, o entrambi con un select *. 
Inoltre sarà possibile aggiungere un filtro 'where name 
like' seguito dalle classiche wildcard valide per i file 
system. La lettura dei risultati avverrà poi invo- 
cando sequenzialmente il comando Read, per ve- 
rificare che siano ancora presenti record da legge- 
re e per impostare il campo m_row con i dati del 
record attuale, cioè creando leggendo ad esempio 
il nome, la data di creazione, la dimensione di un 
file, oppure, per una directory, nome, data di crea- 
zione e file contenuti in essa. 



public bool Read() 


{ 


bool notLast; 


try 


{ 


switch (m_readMode) 


{ 


case ReadMode.AII: 


notLast= m_cursor < m_fileSystemInfos.Length; 


if (notLast) 


{ 



} 



else 



{ 



m_row[0] = "file"; 



m_row[2] = new Filelnfo 
(m_fileSystemInfos[m_cursor].FullName).Length; 



} 



m_cursor+ + ; 



return true; 



} 



return false; 



case ReadMode.File: 



notLast = m_cursor < m_files.Length; 



if (notLast) 



{ 



m_row[0] = "file"; 



m_row[l] = m_files[m_cursor].Name; 
m_row[2] = m_files[m_cursor].Length; 
m_row[3] = m_files[m_cursor]. 

CreationTime; 
m_cursor++; 
return true; 



} 



return false; 



case ReadMode. Directory: 



notLast = m_cursor < 

m_fileSystemInfos.Length; 



if (notLast) 



{ 



m_row[0] = "dir"; 



m_row[l] : 



m_directories[m_cursor].Name; 



m_row[2] = 

m_directories[m_cursor].GetFiles().Length; 
m_row[3] = m_fileSystemInfos 

[m_cursor]. CreationTime; 
m_cursor++; 



return true; 



} 



return false; 



} 



return false; 



} 



catch (UnauthorizedAccessException uex) 



{ 



m_row[2] = "Accesso negato" 



m_cursor++; 



return true; 



> 50 /Settembre 2006 



http://www.ioprogrammo.it 



Massimo riutilizzo minimo sforzo I ▼ DATABASE 



} 



catch(Exception ex) 



{ 



throw new FileSystemException("Errore 

di sintassi nella query o directory non trovata" 



}} 



Le classi create interagiscono strettamente fra di loro, 
come mostrato nel sequence diagram della seguente 
figura che riassume quanto verrà realizzato nell'ap- 
plicazione di esempio. 



UN'APPLICAZIONE 
DI PROVA 

Con le classi realizzate, quindi con il nuovo FileSy- 
stemProvider si può ora realizzare un'applicazione 
che effettua delle ricerche in una data directory del fi- 
le system. L'interfaccia dell'applicazione è mostrata 
in figura 3, e naturalmente tralasciamo la realizzazio- 
ne dei controlli e delle finestre, rinviando al codice 
contenuto nel ed in allegato. La parte interessante av- 
viene al clic sul pulsante cerca: 

private void btQuery_Click(object sender, EventArgse) 

J 

string connString = "path = " + 

txtDirectory.Text; 
try 

{ 

using (FileSystemConnection conn = new 

FileSystemConnection(connString)) 

{ 

conn.Open(); 

FileSystemCommand cmd = 
(FileSystemCommand) conn.CreateCommand(); 

cmd.CommandText=txtQuery.Text; 

FileSystemDataReader dr= 
(FileSystemDataReader) cmd.ExecuteReader(); 

Prepare ListView(dr); 

ListViewItem item; 






n~BW 



Directory ICAWinnt 



-Inlxl 

Sfoglia 



■ : i '■■■•■' ■■.-:.■■ p*! iic.Ei-.'.Eifi"; ::.;::■ i lfl=E- eli-: ó\W-> ÌCW 'sebo : , iT; --? ri C a'-'.Eift": i 

file: 'select files'; per ricavale le dii 'seiecì dir . pai filmare la select * usate ad 
esempio 'sele: : : " wiisr* -lame like 'a" 



nani 



Query select " where narne like 'a" 



Risulf 



T | Usa Query | 
| Ceica | 





| Name 


DirSiis Or Files» 


I CreationTime 


i^d. 


addins 


1 


11712/2001 17.37.' 


L_?dir 


Acoiunte 


2 


01 707/2004 10. 25.( 


LJdir 


AppPatch 


S 


11712/2001 17.37/ 


i_7dir 


d^ScAÒij 


3 


21703/200515.54.1 


Jlile 


ActiveSehjp Log.BAK 


11410 


08705/2002 12.07.9 


J file 


AoiiveSeiLip LogM 


11478 


08/05/20021 2. 07.E 


Jlile 


AdvPack.log 


67536 


15712/2005 3.53.07 


Jlile 


ALVIEWER.NI1 


554 


21705/200212.44./ 


<l 



listViewl.Items.Clear(); 



errorProvider.SetError(txtQuery, ""); 



errorProvider.SetError(txtDirectory, ""); 



while(dr.Read()) 



{ 



item = new ListViewItem(dr[0].ToString()); 



if (item.Text == "dir") 




item.Imagelndex = 0; 



else if (item.Text == "file") 

item.Imagelndex = 1; 
item.SubItems.Add(dr[l].ToString()); 



item.SubItems.Add(dr[2].ToString()); 



item.SubItems.Add(dr[3].ToString()); 



listViewl.Items.Add(item); 



}}} 



OpenO 



-*o 



■:-■■■ C'i stoCoi-ii^Fs.-.iir 



l:FileSjstemCor 
FilaSystemCommdrid(cmdText.mnn) 

V "\ 

= ExecuteReaderQ ._ I 



- "i *-y-/s!«rr:[>3lsR*ad49'«f i r,..-rr..3'i 



> 



FileS^tamDataRal 





er.R^dQ)]: 


obje 


l> G^v.2; 


SCI) 


— *v 








ohject- 




!jj 


_r 













Fig. 2: L'applicazione di ricerca in azione 



Fig. 3: Sequence diagram di una ricerca 

catch (Exception ex){ 

MessageBox.Show(ex.Message); 
» 

Chi ha già avuto a che fare con i data providerADO.NET 
per l'accesso ai database noterà la perfetta analogia 
dei concetti e dell'utilizzo delle classi. Basta creare una 
connessione, aprirla, quindi creare un comando, con 
una sorta di linguaggio simil-sql, ad esempio un se- 
lect dir o select files, ed eseguirlo per ottenere un Da- 
taReader. Infine utilizzare quest'ultimo per scorrere i 
risultati ed aggiungerli ad una ListView. 



CONCLUSIONI 

Abbiamo visto come realizzare un DataProvider per- 
sonalizzato utilizzando le interfacce messe a disposi- 
zione dal .NET Framework, ed i concetti classici dei 
provider per l'accesso ai database diADO.NET . Non 
vi resta che cercare di migliorarlo aggiungendo le ca- 
ratteristiche non implementate, oppure creare il pro- 
vider che può servire a risolvere un vostro problema 

Antonio Pellerìtì 




L'AUTORE 



Potete rivolgere 
domande di 
chiarimenti o ulteriori 
richieste all'autore 
all'indirizzo 
antonio.pelleriti@iopro 
grammo.it, o ancora 
sul forum di 
loProgrammo 
(http://forum.ioprogra 
mmo.net) o sul sito 
www.dotnetarcriitects.it. 



http://www.ioprogrammo.it 



Settembre 2006/ 51 ► 



NETWORKING T ■ Visual Basic.NET e la rete 



M EHI UN FTP 

NEL TUO BROWSER 

CREIAMO UN CLIENT FTP CHE VIVE ALL'INTERNO DI EXPLORER. UTILISSIMO PER UPLOADARE 
FILE IN REMOTO SENZA SCOMODARE PROGRAMMI DI TERZE PARTI. IMPAREREMO COME 
VB.NET GESTISCE ALCUNE FUNZIONI RELATIVE AL NETWORKING 





"" media conoscenza 
diVB.NET 



Visual Studio 2005 
anche in versione 
Express 



Tempo di realizzazione 



00 



Nella versione 1.0 di .NET, una delle cose 
inspiegabilmente mancanti era il sup- 
porto al protocollo FTP (File Transport 
Protocol). 

Esisteva la possibilità di ricorrere, è vero, a libre- 
rie (anche open source) prodotte da terze parti. 
Tuttavia il supporto FTP introdotto da .NET 2.0 è 
sicuramente una buona notizia. 
Il meccanismo di funzionamento dell'API FTP di 
.NET 2.0 è piuttosto semplice, il workflow dell'o- 
perazione è : 

1. Instanziare un oggetto FtpWebRequest impo- 
standone modalità di connessione e uri 

2. Impostare il comando FTP attraverso la pro- 
prietà method dell'oggetto FtpWebRequest 

3. Eventualmente scrivere sul flusso dei dati dal 
client al server recuperando lo Stream in usci- 
ta attraverso la funzione GetRequestStream 
dell'oggetto FtpWebRequest (questa opera- 
zione serve solo per l'upload dei file verso il 
server) 

4. Recuperare la risposta del server attraverso la 
funzione GetResponse dell'oggetto FtpWeb 
Request che restituisce un oggetto di tipo 
FtpWebResponse e, attraverso questo, recu- 
perare eventualmente anche il flusso di dati 
dal server verso il client con il metodo 
GetResponseStream. 

Ad esempio, per scaricare un file da un server 
FTP è sufficiente un codice di questo tipo: 

Public Sub DownloadFile(ByVal uri As Uri, ByVal 

localFilename as String, ByVal credentials As 
NetworkCredential) 
Dim ftpRequest As FtpWebRequest = 

FtpWebRequest. Create(Url) 
ftpRequest. Credentials = credentials 
ftpRequest. Method = 

WebRequestMethods.Ftp.DownloadFile 
ftpRequest. UseBinary = True 
ftpRequest. KeepAlive = False 
Dim ftpResponse As FtpWebResponse = 

ftpRequest. GetResponse 



IO. StreamReader(ftpResponse. GetResponseStream) 
Dim writer As New 

IO. Stream Writer(localFilename) 
writer. Write(reader.ReadToEndQ) 
reader.Close() 



writer.CloseQ 



ftpResponse. CloseQ 



Dim reader As New 



End Sub 

Recentemente mi è capitato di utilizzare questa tec- 
nologia per applicazioni web. Il problema è quello, 
abbastanza diffuso tra gli sviluppatori, della pubbli- 
cazione di applicazioni web presso provider esterni, 
dove non si ha il controllo sulle permissions asse- 
gnate alle directory del file system. Il provider, infat- 
ti, prevede soltanto una directory nella quale l'uten- 
te web aveva anche diritti di scrittura: la directory 
/public del sito. 

Mi sono trovato ad installare applicazioni, sviluppa- 
te da terzi, che invece richiedevano percorsi di scrit- 
tura diversi, purtroppo non parametrizzati. 
La prospettiva era quindi quella di rivedere tutto il 
codice per cambiare i percorsi di scrittura. 
Grazie all'API FTP di .NET 2.0 è invece stato possibi- 
le scrivere non attraverso il file system, ma attraver- 
so l'account FTP che il provider metteva a disposi- 
zione. 

Sulla scorta di questa esperienza mi è allora venuta 
l'idea di sviluppare un vero e proprio client FTP da 
utilizzare via web, per esplorare fino in fondo le pos- 
sibilità offerte dall'API. 



FTP WEB CLIENT 

L'applicazione, per adesso sviluppata al solo scopo 
sperimentale, si propone di : 

• Consentire il browsing delle cartelle di un server 
FTP 

• Consentire la cancellazione, il download e l'u- 
pload di files 

Il tutto non attraverso una Windows Application, ma 
inASRNET. 



► 52 /Settembre 2006 



http://www.ioprogrammo.it 



Visual Basic.NET e la rete ■ T NETWORKING 



PANORAMICA 
SULL'APPLICAZIONE 

Prima di vedere nel dettaglio alcuni particolari del- 
l'implementazione, analizziamo il funzionamento 
dell'applicazione finita. 

L'applicazione si installa semplicemente copiando 
la directory che la contiene sul disco fisso e configu- 
rando, nel server web US, una directory virtuale in 
corrispondenza di tale directory. 
Poniamo quindi che in US sia stata configurata la 
directory virtuale con il nome ftpclient, aprite il 
vostro browser all'indirizzo http://localhost/ftp- 
client ed apparirà la maschera di collegamento al 
server FTP di cui in figura 1. 



Fé. g.tft. £«.*,..* fr.i-.ti 


|«Mrtl l 


JMft * 


Cw» Prrfp» f- ' , ^i- U t 


Dijriuu 


^IQw 


G ,il O 


G*a & . <£ i^ftdbn* ^StiHSfl M 


FTP 


• AMOMl 


web client 


J0KoGi 






:rv? 'ii.-o ~P 








Login 








password 








Ji.il 





Fig. 1: La maschera dì login iniziale 

La maschera di login chiede la uri del server FTP il 
nome utente e la password per la connessione. 
Una volta fornite queste informazioni, la web appli- 
cation presenta una vista sulla directory principale 
(root) del server FTP (figura 2). 




Fig. 2: Il browsing FTP da Web 

Per effettuare le prove abbiamo qui configurato il 
servizio FTP di US puntandolo direttamente sul 
disco C: della macchina che quindi risponde all'uri 
ftp://localhost . 

Cliccando sulle cartelle si apre la directory inferiore, 
mentre cliccando sui files si procede al download. 
Da notare le icone delle directory e dei files, le stesse 
del sistema operativo, vedremo successivamente 
come ottenerle. 



Sul resto non c'è molto altro da dire: c'è un campo 
upload per i files da caricare, un link per cancellare il 
file, una barra degli indirizzi e un bottone per il 
logout. Insomma, seppur spartano, un client FTP 
vero e proprio ma . . . nel browser! 
Ma andiamo ad analizzare adesso la struttura ed i 
passi salienti dell'applicazione. Non ci soffermere- 
mo molto sui particolari dell'interfaccia (che nel 
codice è stata mantenuta volutamente semplice per 
rendere più chiara la logica applicativa). 





L'applicazione Web illustrata in 
questo articolo e allegata al CD è 
perfettamente funzionante e può 
essere utilizzata liberamente. 
Attenzione però a pubblicarla in 
un sito Web in modalità non 
protetta da password: gli utenti 
anonimi del sito potrebbero 
compiere qualsiasi operazione 
(cancellazione o upload) nei 
confronti di server FTP di cui 
conoscessero le credenziali di 
autenticazione. Queste operazioni 
verrebbero però registrate dal 
server FTP come provenienti dal 
vostro sito web e quindi voi ne 



sareste responsabi 
È pertanto consigliabile utilizzare 
l'applicazione soltanto in aree 
riservate del sito o in intranet, 
oppure modificare l'applicazione 
aggiungendo un proprio logging 
delle operazioni compiute dagli 
utenti. 

Per consentire una prova "sul 
campo" l'applicazione è stata 
pubblicata all'indirizzo 
http://www.smelzo.it/ftp in 
modalità "demo" ovvero senza la 
possibilità di effettuare la 
cancellazione e la modifica di 
files. 



IL PROGETTO 

Per lo sviluppo del nostro mini-progetto abbiamo 
utilizzato Visual Studio 2005 nel quale abbiamo 
impostato un nuovo progetto web come vediamo in 
figura 3. 



ita 



■ 



J 



~ar 



• rtJlia* 



n^j. 



Fig. 3: Un nuovo progetto Web in Visual Studio 2005 

Lo sviluppo web in Visual Studio 2005 ha fatto vera- 
mente dei passi avanti notevoli: adesso è infatti pos- 
sibile inserire le nostre classi nella cartella 
App_Code del progetto ed è possibile eseguire il 
debug senza dover ricompilare ogni volta. Inoltre, 
nelle pagine aspx, oltre al modello code-behind 
(dove codice risiede in file separati) è adesso pos- 



http://www.ioprogrammo.it 



Settembre 2006/ 53 ► 



NETWORKING T ■ Visual Basic.NET e la rete 




sibile finalmente utilizzare il modello online dove, 
come in ASP classico, possiamo scrivere il codice 
direttamente nella pagina (questa non è però la 
modalità predefinita: per attivarla quando inseria- 
mo nel progetto una nuova pagina aspx dobbiamo 
deselezionare la casella di spunta "Inserisci codice in 
file separato" come mostrato in figura 4). 
Naturalmente potevamo utilizzare il modello inline 
anche nelle versioni precedenti di Visual Studio, sol- 
tanto che adesso abbiamo il pieno supporto 
Intellisense anche all'interno del tag <script> che 
ospitano il codice lato server (vedi figura 5). 



J 



II 



1 



Mestaste Ffc * ri»r$* DttabtsaSQL Datasti 



fteport 



Cantralo 
Utente We... 



FfeJScrvt Ffed 

configuralo.. 



~~w\ r fcnsa-fco] coda m fte «fmto| 
V ^steacna pagina master 



toa»jnoj 



Fig. 4: Utilizzo dei modello inline per le pagine 
ASP.NET 





i] ocript v ="set:ver"> 






Private ReadOtily Property ft 


pUri [) A3 Uri 






Get 








Aboi Iti ad in 


•1 




■% Acce55Datd5ouri:e 


^ 




En 


' ^ AccessOat^ourceView 
< ' f . AccessVioldtionExceptiori 








Pe 


j Action(Of T) 

ActivationContext 
; Activator 
L P ActiveDirectoryConnectionProtection 

ActiveDirectoryMembershipProvider 




Às String 

luest. ("frpUrl 
M ftpUrl) TI] 
Lth(Uri.UiriSc 






ActiveDirectQryMembershipUser 


-1 


£ ftpUrl 
:1 




Comuni Tutti 










1 Else 





Fig. 5: Supporto intellisense al modello inline 

Naturalmente anche noi abbiamo a cuore il paradig- 
ma della separazione e della riutilizzabilità del codi- 
ce, solo che ci sembra spesso esagerato e dispersivo 
ricorrere allo sviluppo di librerie esterne per proget- 
ti di piccole e medie dimensioni. Quindi abbiamo 
optato per l'inserimento della nostra logica applica- 
tiva in file di classi nella cartella App_Code (classi 
che tra l'altro possono essere tranquillamente riuti- 
lizzate in progetti diversi) e l'utilizzo dei file aspx per 
la sola logica di presentazione. 
Per prima cosa abbiamo quindi inserito nel proget- 
to, nella cartella App_Code, il file di codice conte- 
nente le classi deputate a gestire il colloquio FTP In 
questo file abbiamo creato la classe di base, chiama- 
ta FtpClient, che verrà utilizzata dal lato ASRNET per 
colloquiare con il server FTP 
Come possiamo vedere dalla figura 6, nella classe 
FtpClient sono state dichiarate quattro variabili a 



livello di classe: 

• Uri - di tipo Uri che rappresenta l'uri della richie- 
sta FTP 

• Credentials - di tipo NetworkCredential che rap- 
presenta le credenziali di autenticazione presso il 
server 

• Proxy- di tipo IWebProxy che rappresenta l'even- 
tuale proxy da utilizzare nella connessione 

• Port - di tipo Integer che rappresenta la porta 
TCP per la connessione (normalmente la 21) 




FlpCIent 


&m 


- Campi 


.■> Credentials 


j* Port 


jt Proxy 


f Uri 


- Metodi 


. » QeateFtpWebRequest 


•» Deleteffe (oltre a 2 ovetto*!) 


v DówhkradFire (óltre a 2 overioad) 


* list (otre a 2 overtoad) 


» Mew (ofcie e l overìoad) 


w UptoadFte (ohe a 2 ovetto*)) 




Fig. 6: Struttura della classe FtpClient 

Tali variabili vengono valorizzate nei costruttori di 
cui vengono fornite due versioni: 

Sub New(ByVal uri As Uri, ByVal credentials As 

System. Net. NetworkCredential, ByVal proxy As 
IWebProxy, ByVal port As Integer) 
Me. Uri = uri 
Me. Port = port 
If uri. Port <> port Then 

'aggiunge la porta se mancante nella uri 
Dim builder As New UriBuilder(url) 
builder.Port = port 
Me. Uri = builder.Uri 
End If 

Me. Credentials = credentials 
Me. Proxy = proxy 
End Sub 



Sub New(ByVal uri As Uri, ByVal userName As String, 

ByVal password As String, ByVal port As Integer) 

Me.New(url, New NetworkCredential(userName, 

password), Nothing, port) 

End Sub 

Dove nel secondo costruttore, più semplice e di uso 
più comune, si omette il proxy e si costruisce diret- 
tamente la credenziale a partire da userName e pas- 
sword. 

È stata poi aggiunta una funzione, di uso comune a 
tutti i metodi, per creare la richiesta al server FTP: 

Private Function CreateFtpWebRequest(ByVal method 
As String, Optional ByVal useBinary As Boolean = 



> 54 /Settembre 2006 



http://www.ioprogrammo.it 



Visual Basic.NET e la rete ■ T NETWORKING 



True) As FtpWebRequest 



Dim ftpRequest As FtpWebRequest = 

FtpWebRequest. Create(Url) 
ftpRequest. Credentials = Me.Credentials 



ftpRequest. KeepAlive = False 



ftpRequest. UseBinary = useBinary 



ftpRequest. Method = method 



If Me.Proxy IsNot Nothing Then 



ftpRequest. Proxy = Me.Proxy 



End If 



Return ftpRequest 



End Function 

È da sottolineare che il parametro method, 
rappresenta il comando FTP da inviare al ser- 
ver. Non è necessario scrivere manualmente 
la stringa del comando in quanto è possibile 
utilizzare le costanti esposte dalla classe 
System. Net. Web RequestMethods.Ftp che 
sono autodescrittive. 

I metodi pubblici esposti dalla classe sono: 
DeleteFile - che invia un comando di cancel- 
lazione del file 

DownloadFile - che scarica un file dal server 
come flusso 

List - che ottiene una lista di oggetti contenu- 
ti in una directory del server 
UploadFile - che invia un file al server come 
matrice di byte 

I comandi gestiti dalla classe sono solo una 
parte di quelli disponibili; mancano, ad esem- 
pio, quelli per rinominare, creare e cancellare 
le directory, ma per adesso non si è voluto 
complicare troppo le cose e limitarsi solo 
all'essenziale. 



IL PARSIIMG DEL LIST 

Dei quattro metodi citati sicuramente il più 
complesso è il List. Di base TAPI FTP dispone 
di due comandi per ottenere la lista di oggetti 
di una directory nel server : 
WebRequestMethods. Ftp. List Directory e 
WebRequestMethods.Ftp.ListDirectory 
Details. 

Il primo comando è inadatto ai nostri scopi 
perché fornisce soltanto il nome degli oggetti 
senza dirci, ad esempio, se si tratta di file o 
directory. 

Il secondo invece è più completo perché for- 
nisce la lista comprendente informazioni su: 
natura dell'oggetto (file o directory), dimen- 
sioni e data di creazione. 
Il problema è che la struttura della lista dipen- 
de dal server, nei sistemi Unix e Linux la 



risposta sarà del tipo illustrato in figura 7, 
mentre per i server Windows basati su US la 
risposta sarà quella mostrata in figura 8. 



f 


.a* 










■ 




f mritHff 


1 




t ESa 
















H- 




Fig. 7: Listing su server FTP Unix/Linux 




Fìg. 8: Listing so server FTP US 

Abbiamo quindi dovuto creare una classe 
astratta, FtpListParserBase, che poi verrà ere- 
ditata dalle classi deputate ad interpretare la 
risposta del server (noi abbiamo implementa- 
to soltanto FtpListParserlIS e FtpListParser 
Unix) ognuna di queste sottoclassi deve avere 
un metodo pubblico, Match, che, partendo 
dalla prima linea di testo ricevuta dal server, 
determina se è essa a poter effettuare il par- 




Fìg. 9: Classi per il parsing del listing 

sing oppure no. 

Senza scendere qui troppo in dettaglio sul 
parsing (effettuato con le Regular Expressions) 
basti dire che le classi specializzate di 
FtpListParserBase si comportano tutte nello 
stesso modo prendono una matrice di linee 
di testo, ne interpretano il contenuto e creano 
una lista corrispondente di oggetti. Questi 
oggetti sono basati su un'altra classe, 
FtpListltem, che raccoglie le informazioni 
dalla linea di testo inviata dal server dimen- 
sioni, data, nome ecc.. 



http://www.ioprogrammo.it 



Settembre 2006/ 55 ► 



NETWORKING T ■ Visual Basic.NET e la rete 










FtpListltem 


a 




Class 






+ Campi 




- Proprietà 


Jjf BaseUri 






_ff Date 






jfp IsDirectory 






Jff Narne 






J* 5ize 






jf Uri 









ft\Zj^^^^^^^^F F/g. IO: Classi FtpListltem 
rncA «flirti 




COSA VUOL 
DIRE FTP? 

L'FTP, acronimo di File 

Transfer Protocol 

(protocollo di 

trasferimento file), è 

un servizio che 

garantisce il 

trasferimento di file tra 

client e server. 

Il protocollo FTP che ha 

subito una lunga 

evoluzione negli anni 

(il primo meccanismo 

di trasmissione file 

risale al 1971, fu 

sviluppato presso il 

MIT) è ancora 

largamente utilizzato 

soprattutto dagli Host 

Providers per garantire 

ai clienti l'accesso al 

proprio sito web. 



Tutti gli oggetti FtpListltem vengono raccolti dal 
parser in un insieme Ftp List che dispone di metodi 
per l'ordinamento e la contestualizzazione degli ele- 
menti contenuti. 

Il nostro metodo List della classe FtpClient si pre- 
senterà quindi, alla fine, così: 

Public Function List() As FtpList 

Dim ftpRequest As FtpWebRequest = _ 
Me.CreateFtpWebRequest(WebRequestMethods.Ftp.Lis 
tDirectoryDetails, False) 
Dim ftpResponse As FtpWebResponse = 

ftpRequest. GetResponse 
Dim stream As IO.Stream = 

ftpResponse. GetResponseStream 
Dim reader As New IO.StreamReader(stream) 
Dim lines As New List(Of String) 



While Not reader.Peek 



-1 



lines. Add( reader. ReadLine) 



End While 



If lines. Count = Then 



ftpResponse. Close() 



Return FtpList. Empty(Url) 



End If 



ftpResponse. CloseQ 



Dim parser As FtpListParserBase 



If FtpListParserUnix.Match(iines(0)) Then 
parser = New FtpListParserUnix(Me.Url) 

Elself FtpListParserIIS.Match(iines(0)) Then 
parser = New FtpListParserlIS(Me.Url) 

Else 



parser = Nothing 



End If 



If parser Is Nothing Then 



Throw New WebException("Linea non 

riconosciuta ") 



End If 



Return parser. Parse( lines. ToArray) 



End Function 

Dove si leggono le linee trasmesse dal server, 
si sceglie il parser adatto e si utilizza per resti- 
tuire un insieme di oggetti FtpListltem. 
Gli altri metodi esposti dalla classe FtpClient 
sono invece più semplici. 



CANCELLAZIONE DI FILE 

Il codice per la cancellazione di un file dal server FTP 
sarà: 



Public Function DeleteFileQ As String 
Dim ftpRequest As FtpWebRequest = _ 
Me.CreateFtpWebRequest(WebRequestMethods.Ftp.De 

leteFile) 
Dim ftpResponse As FtpWebResponse = 

ftpRequest. GetResponse 



Dim r As String 



ftpResponse. StatusDescription 



ftpResponse. Close() 



Return r 



End Function 



Il valore di ritorno sarà, in questo caso la stringa con- 
tenente il messaggio di ritorno del server. 



DOWNLOAD DI FILE 

La funzione di download, invece, restituisce un 
flusso (stream) dei dati provenienti dal server 

FTP: 

Public Function DownloadFile() As IO.Stream 

Dim ftpRequest As FtpWebRequest = 
Me.CreateFtpWebRequest(WebRequestMethods.Ftp.Do 

wnloadFile) 
Dim ftpResponse As FtpWebResponse = 

ftpRequest. GetResponse 
Return ftpResponse. GetResponseStream() 
End Function 



UPLOAD DI FILE 

Conclude la serie di funzioni esposte dalla classe 
FtpClient il metodo UploadFile: 

Public Function UploadFile(ByVal b() As Byte) As 

String 
Dim ftpRequest As FtpWebRequest = 
Me.CreateFtpWebRequest(WebRequestMethods.Ftp.Up 

IoadFile) 
ftpRequest. ContentLength = b.Length 
Dim requestStream As IO.Stream = 

ftpRequest. GetRequestStream 
requestStream. Write(b, 0, b.Length) 
requestStream. Close() 
Dim ftpResponse As FtpWebResponse = 

ftpRequest. GetResponse 



Dim r As String 



ftpResponse. StatusDescription 



ftpResponse. Close() 



Return r 



End Function 



► 56 /Settembre 2005 



http://www.ioprogrammo.it 



Visual Basic.NET e la rete ■ T NETWORKING 



Anch'esso, come deleteFile, restituisce la stringa 
contenente il messaggio di ritorno del server, tutta- 
via richiede, come parametro la matrice di byte che 
rappresenta il file da caricare. 



IL LATO WEB 

Sul versante web, la nostra pagina ASENET non farà 
altro che utilizzare la classe FTF client definita in 
App_Code. 

Fer l'implementazione non è stato utilizzato il 
modello dei controlli ASENET collegato agli Eventi 
(Textbox, Button ecc.), perché personalmente 
ritengo che non faccia altro che complicare la vita. . . 
Freferisco invece attenermi al flusso Request»» 
Response che è sempre alla base del ciclo della pagi- 
na. Su OnLoad della pagina, quindi, si innesta tutto 
il ciclo delle operazioni. 

Si controlla se la Request o la Session contengono i 
valori di autenticazione, se non li contengono verrà 
mostrata la maschera di login, altrimenti verrà effet- 
tuato il Listing richiamando metodo: 

Private Sub GetList(ByVal strLIrl As String) 
Dim u As New Uri(strUrl) 



Dim listing As FtpList 



FtpClient.List(u, 
Me.ftpUser, Me.ftpPwd) 



listing. DefaultSortQ 



Me.result.InnerHtml 



Dim sb As New System. Text.StringBuilder 

sb.Append("<table border=0 width=""100%"" 
cellspacing = '0'>") 



If Not listing. IsRoot Then 



FormatDirectory(sb, listing. Parentltem, 



True) 



End If 



For Each item As FtpListltem In listing 



FormatItemRow(sb, item) 



Next 



sb.Append("</table>") 



Me.result.InnerHtml = sb.ToString 



End Sub 

GetList richiama una serie di metodi definiti 
nello script della pagina volti a formattare 
l'output, da notare anche che per richiamare la 
funzione List di FtpClient abbiamo utilizzato 
una versione statica del metodo che avevamo 
approntato nella classe FtpClient. I metodi sta- 
tici (shared in VB.NET) sono molto comodi 
perché permettono di richiamare al volo una 
funzione senza dover tutte le volte instanziare 
un nuovo oggetto. 

Prima di effettuare il browsing della directory 
corrispondente all'URL corrente, OnLoad 



dovrà però valutare se tra le operazioni richie- 
ste c'è una cancellazione o un upload di file, 
queste operazioni vengono racchiuse in due 
metodi: 

Private Sub EvalDelete() 

Dim deIRequest As String = Request("del") 
If Not String. IsNullOrEmpty(delRequest) Then 
Try 

Dim u As New Uri(delRequest) 
Dim msg As String = 
FtpClient. DeleteFile(u, Me.ftpUser, Me.ftpPwd) 
msg = String. Format("Cancellazione file 

{0} : {1}", u.ToString, msg) 
WriteClientMessage(msg) 



Catch ex As Exception 



WriteClientMessage(ex.Message) 



End Try 



End If 



End Sub 



Private Sub EvalUploadQ 



If Request. Files.Count > Then 



Dim filename As String = 
IO.Path.GetFileName(Request.Files(0).FileName) 
If String. IsNullOrEmpty(filename) Then 
Return 



End If 



Dim reader As New 
IO.BinaryReader(Request.Files(0).InputStream) 
Dim b() As Byte = 
reader. Read Bytes(Request.Files(0).ContentLength) 



Try 



Dim u As New Uri(ftpUrl & "/" & 



filename) 



Dim msg As String = 
FtpClient. UploadFile(u, Me.ftpUser, Me.ftpPwd, b) 
msg = String. Format("Upload file {0} : 

{!}", filename, msg) 



WriteClientMessage(msg) 



Catch ex As Exception 



WriteClientMessage(ex.Message) 



End Try 



End If 



End Sub 

EvalDelete funziona semplicemente esami- 
nando se nella Request esiste il valore "del" che 
sarà corrispondente alla uri del file da cancel- 
lare, se esiste richiama la funzione statica 
DeleteFile di FtpClient . 

EvalUpload, invece, valuta se il flusso Request 
contenga o meno un Post di file ed eventual- 
mente richiama la funzione statica 
UploadFile di FtpClient. Resta da vedere come 
viene gestita l'operazione di download del 
nuovo file. 

Per effettuare il download è stato necessario 
approntare una nuova pagina ASP.NET, 




http://www.ioprogrammo.it 



Settembre 2006/ 57 ► 



NETWORKING T ■ Visual Basic.NET e la rete 





Francesco Smelzo è 

specializzato nello 

sviluppo in ambiente 

Windows con 

particolare riferimento 

ad applicazioni in 

ambiente .NET sia web- 

oriented che desktop. 

Il suo sito web è 

www.smelzo.it . Come 

sempre è a 

disposizione per 

ricevere suggerimenti o 

richieste sull'articolo 

all'indirizzo di posta 

elettronica 

fra ncesco@smelzo.it 



DownloadFile.aspx, alla quale tutti i nomi dei 

file che compaiono nella tabella verranno 

linkati. 

Il listato di DownloadFile.aspx è comunque molto 

semplice: 

<%@ Page Language="VB" %> 
<script runat= "server" > 

Public ReadOnly Property Url() As String 
Get 

Return Request("get") 
End Get 



End Property 



Protected Sub Page_Load(ByVal sender As Object, 
ByVal e As System. EventArgs) 



Dim fStream As IO.Stream 



Try 



Dim u As New Uri(Url) 



fStream = FtpClient.DownloadFile(u, 

Session("user"), Session("pwd")) 
Me.Response.ContentType = "application/x- 

download" 
Me. Response. AddHeader("content- 

disposition", "attachment; filename=" & 
IO.Path.GetFileName(Url)) 



Dim reader As New 



IO.BinaryReader(fStream) 



Dim b(256) As Byte 



Dim count As Integer = reader. Read 

(b, 0, 256) 



While count > 



Me.Response.BinaryWrite(b) 



count = reader.Read(b, 0, 256) 



End While 



reader.Close() 



Me.Response.OutputStream.Close() 



Catch ex As Exception 



Me. Response. ClearQ 



Me.Response.ContentType = "text/html" 
Me. Response. Write(ex.ToString) 



Me. Response. Write("<br>") 



Me. Response. Write("URL:" & Me. Uri) 



End Try 



End Sub 



</script> 

In pratica in OnLoad si richiama la funzione 
statica DownloadFile di FtpClient e si legge il 
flusso che restituisce scrivendolo nella 
Response. 

Da notare che il browser capisce che si tratta 
di un file da scaricare (e non di una pagina da 
mostrare) in quanto gli abbiamo passato, 
nella Response, un apposito Header content- 
disposition e un ContentType application/x- 
download. 



LE ICONE 

Resta da vedere come abbiamo ottenuto le icone 
delle directory e dei vari tipi di file senza dover 
approntare decine di GIFS. 

Per fare questo in App_Code abbiamo predisposto 
un altro file, shFilelcon.vb, che utilizza TAPI Win32 
richiamando la funzione SHGetFilelnfo di 
shell32.dll del sistema operativo, questa ci consente 
di ricavare la bitmap con l'icona del file passandogli 
semplicemente un nome di file con la relativa esten- 
sione (da notare che il file non deve essere fisica- 
mente presente su disco, basta il nome). La stessa 
API consente anche di ottenere le bitmap delle icone 
utilizzate dal sistema operativo per le directory. 
Abbiamo poi predisposto un'altra pagina 
ASP.NET chiamata icon.aspx il cui lavoro consi- 
ste unicamente di recuperare la bitmap dal nome 
di file passato nella Request e salvarla nel flusso 
Response: 



Dim bmpBase As New Bitmap(16, 16) 
Dim bmp As Bitmap 
If IsDirectory Then 
bmp = 
iconMaker.GetFolderIcon(shFileIcon.IcoSizeEnum.smal 

I, False).ToBitmap() 
Else 

bmp = iconMaker.GetFileIcon(Extension, 
shFileIcon.IcoSizeEnum.small).ToBitmap() 
End If 
Dim g As Graphics = 

Graphics. Fromlmage(bmpBase) 
g.Clear(Color.White) 
g.DrawImage(bmp, 0, 0) 
Response. ContentType = "image/gif" 
bmpBase.Save(Response.OutputStream, 

Imagi ng.ImageFormat. Gif) 



Per ottenere la gif corrispondente nella pagina è suf- 
ficiente utilizzare icon.aspx come src di un tag 
HTMLimg: 

<img src="icon.aspx?n=file.txt"> 



CONCLUSIONI 

In questo articolo abbiamo visto come gestire il pro- 
tocollo FTP in .NET 2.0. 

Il nostro obbiettivo era un'applicazione web in 
grado di offrire un servizio di Client FTP tuttavia le 
tecniche trattate e i listati allegati al Cd si prestano 
ad essere adattati e riutilizzati a tutte le situazioni in 
cui sia necessario utilizzare questo diffusissimo pro- 
tocollo. 

Francesco Smelzo 



► 58 /Settembre 2006 



http://www.ioprogrammo.it 



MOBILE T m Remote Data Access 



SINCRONIZZARE I DATI 
TRA SERVER E PALMARE 

SE ABBIAMO UNA RETE DI PALMARI, I DATI PRESENTI IN UN DISPOSITVO DEVONO 
SICURAMENTE ESSERE SINCRONIZZATI CON UN DATABASE CENTRALE. SCOPRIAMO 
COME GESTIRE UPLOAD MULTIPLI EVITANDO EVENTUALI CONFLITTI 




U CD U WEB 

SiiicroiiizzazioiwConRDA.zii) 



un 




REQUISITI 



Conoscenze richieste 



i i Basi di C# 



Windows XP/2003, .net 
Framework 2.0, 
Microsoft Visual Studio 
.NET 2005, Windows 
Mobile 5.0 SDK, SQL 
Server 2005 Mobile 
Edition 



Tempo di realizzazione 







Nei precedenti due articoli, abbiamo 
affrontato buona parte delle problema- 
tiche che riguardano la realizzazione di 
software per dispositivi mobili. Si è parlato 
della scelta del device, della piattaforma, delle 
funzionalità e di come realizzare una interfac- 
cia utente comoda da usare anche su schermi 
di piccole dimensioni. 

Abbiamo anche visto come poter facilmente 
integrare il servizio web offerto da MapPoint 
per generare una mappa relativa all'indirizzo 
del cliente selezionato. Abbiamo però lasciato 
per ultima una esigenza molto sentita: la sin- 
cronizzazione dei dati. 

Una applicazione come quella descritta negli 
articoli precedenti infatti, difficilmente sarà 
confinata al solo uso su dispositivi mobili. 
Molto più probabilmente, i dati usati dalla 
nostra applicazione, saranno generati da un 
sito web o da una applicazione gestionale 
aziendale e, i dati di ritorno dal palmare, 
dovranno essere riversati in un DataBase azien- 
dale per poi essere elaborati. 
Tale problematica ha alcuni lati oscuri e molto 
delicati, ma altrettante soluzioni utili alla cor- 
retta gestione della sincronizzazione. 
In questo articolo vedremo quali sono le tecni- 
che più comuni focalizzando l'attenzione su 
quella più economica e semplice da realizzare: 
Remote Data Access (o RDA). 



PERCHE ESISTE IL 
PROBLEMA DELLA 
SINCRONIZZAZIONE? 

Se ci troviamo ad affrontare problematiche di 
sincronizzazione dei dati, siamo sicuramente 
di fronte ad un sistema composto da un 
DataBase centrale, localizzato su un server 
aziendale, ed uno o più DataBase remoti che 
non sono sempre connessi con quello centrale. 
È il caso dell'applicazione che accompagna 
questa serie di articoli. Il DataBase centrale 



conterrà i dati di tutti i clienti, di tutti i prodot- 
ti, gli ordini, le consegne, i fornitori età, men- 
tre quelli remoti, installati sui palmari degli 
agenti, conterranno solo una parte dei dati: 
quelli che servono all'agente per il suo lavoro. I 
dati però, ogni tanto, dovranno essere sincro- 
nizzati: quelli nuovi presenti sul DataBase cen- 
trale, come nuovi prodotti o aggiornamenti di 
prezzi, dovranno essere scaricati sui DataBase 
locali e gli ordini o eventuali modifiche alle 
anagrafiche, dovranno essere inviati dal client 
al server centrale. 

E subito si possono individuare due importan- 
ti problematiche: l'accesso al DataBase centra- 
le da parte del dipositivo ed i conflitti sui dati. 
Il primo problema, apparentemente semplice, 
nasconde con se alcune insidie. Innanzitutto, 
come è buona norma, il DataBase centrale non 
sarà esposto su internet. Non è infatti detto che 
i client sincronizzino i dati dall'interno della 
lan aziendale. Bisogna quindi considerare tutti 
gli aspetti relativi alla sicurezza. 
Il secondo problema invece è molto delicato e 
riguarda proprio l'attendibilità dei dati. Quello 
che può accadere infatti è che due o più siste- 
mi remoti, quando sono disconnessi, modifi- 
chino lo stesso dato. Al momento della sincro- 
nizzazione, quale dato va accettato? 
Facciamo un esempio pratico prendendo 
come esempio l'applicazione usata in questi 
articoli. Supponiamo che due rappresentanti, 
la mattina, sincronizzino i loro palmari scari- 
cando, tra l'altro, l'anagrafica clienti, ed escano 
dall'ufficio per il loro consueto giro. Il rappre- 
sentante che chiameremo RA si reca dal suo 
cliente CA per prendere un ordine e, mentre è 
dal cliente, quest'ultimo gli comunica che il 
numero di telefono è errato. RA aggiorna l'ana- 
grafica di CA sul suo palmare, fa l'ordine e salu- 
ta il cliente. 

Per un errore di organizzazione, il rappresen- 
tante RB si reca da CA il quale, dopo avergli 
confermato che è già passato il suo collega, si 
ricorda di aver dato a RA un numero di telefono 



». 60 /Settembre 2006 



http://www.ioprogrammo.it 



Remote Data Access H T MOBILE 



errato e comunica ad RB quello corretto. Il 
nostro rappresentante aggiorna l'anagrafica di 
CA sul suo palmare e procede il suo giro. 
Cosa accade la sera, quando i due agenti rien- 
trano in sede ed aggiornano i dati sul server 
centrale? I dati di CA saranno stati modificati su 
ambedue i palmari. Qual è il dato che si troverà 
sul server? Per la corretta gestione di questa 
particolare problematica, esistono diverse stra- 
de. La più sensata, sicura e, se vogliamo, econo- 
mica da gestire è la parzializzazione dei dati. 
Consiste nel fare in modo che due client non 
possano modificare lo stesso dato, parzializ- 
zando appunto i dati che ogni client gestisce. 
Nel caso della nostra applicazione d'esempio, 
ogni agente dovrebbe avere sul proprio palma- 
re solo i clienti di competenza. In questo modo, 
RB non potrà mai aggiornare i dati di CA sem- 
plicemente perchè il dato non è presente sul 
proprio dispositivo. Un altra strada percorribile 
è quella di usare, per la sincronizzazione dei 
dati, il sistema di repliche di SQL Server. Tale 
sistema è estremamente potente e flessibile e 
consente di attuare delle dettagliate politiche di 
gestione dei conflitti. La sua trattazione però 
esula dallo scopo di questo articolo essendo un 
argomento abbastanza vasto e complesso da 
affrontare. 

Una terza soluzione è quella di gestirsi autono- 
mamente la gestione dei conflitti sui dati. 
Usando opportuni campi delle tabelle, possia- 
mo sapere quando un record è stato modifica- 
to, se ci troviamo di fronte ad un conflitto e pos- 
siamo comportarci di conseguenza. 
È evidente che tale sistema presuppone un 
grosso lavoro di progettazione e di implemen- 
tazione. Ogni soluzione va ponderata in base 
alle reali esigenze e va attentamente analizzata. 
Nel prossimo paragrafo ne analizzeremo uno in 
particolare: RDA (Remote Data Access). 



RDA: CONCETTI BASE 

Remote Data Access è un sistema che consente 
di accedere e scambiare dati tra un dispositivo 
mobile su cui è installato SQL Server 2005 
Mobile Edition ed un server centrale con SQL 
Server 2005. La grossa comodità di RDA è che, 
per la connessione al server, usa US risolvendo 
già implicitamente tutte le problematiche di 
raggiungibilità del server stesso. 
In figura 1 possiamo vedere un tipico schema 
logico di come è possibile strutturare la rete per 
RDA. 

In figura possiamo notare come i PDA si con- 
nettano alla rete lan aziendale sfuttando inter- 
net. Ciò rende possibile la sincronizzazione dei 




DB Server 



Web Server Firewall 




PDA 




^0^ 



T Internet 




Fig. 1: Architettura di una rete 

dati usando un qualsiasi mezzo di connessione, 
sia esso GPRS, UMTS, Wi-Fi, purché l'indirizzo 
pubblico del servizio RDA sia raggiungibile. 
Sempre dalla figura è evidente come solo il ser- 
ver web può essere esposto su internet attraver- 
so il firewall, lasciando il server contente il Data 
Base in una sotto rete separata e non esposta. 
Internamente, RDA è strutturato in due moduli 
diversi: uno sul client, per gestire la comunica- 
zione con il Data Base locale, ed un modulo ser- 
ver il cui scopo è quello di gestire le richieste del 
client. 

In figura 2 è visibile uno schema sintetico di 
come è strutturato RDA. 



U 



Applicazione 




Agente Client 







Cirasase 



Web Server 



115 





Agente Server 



Data Provider 



DB Server 




Da:abase 



Fig. 2: La struttura interna di RDA 



http://www.ioprogrammo.it 



Settembre 2006/ 61 ► 



MOBILE T fl Remote Data Access 




*£^ SUL WEB 



Introduzione a RDA: 

http://msdn2. microsoft. 

com/it- 

it/librarv/ms1 72029. aspx 

Confronto tra RDA 

e Repliche: 

http://msdn2. microsoft. 

com/it- 



it/librarv/ms172916.aspx 

Configurazione 

e protezione: 

http://msdn2.microsoft.co 

m/it- 

it/librarv/ms1 72463. aspx 

Utilizzo di RDA: 

http://msdn2. microsoft. 

com/it- 

it/library/ms172917.aspx 



Lato client, l'agente locale si occupa di traccia- 
re le modifiche ai dati delle tabelle che parteci- 
pano alla sincronizzazione. Quando uno dei 
metodi di RDA viene richiamato, l'agente loca- 
le contatta, attraverso US del server web, l'agen- 
te server che si occupa, attrraverso il data provi- 
der, di comunicare con il DataBase server. 
RDA supporta sostanzialmente tre tipi di 
comandi molto semplici: 

• Pulì: le tabelle ed i dati da sincronizzare ven- 
gono scaricati dal server. I dati da scaricare 
sul client possono essere filtrati attraverso la 
clausola where della query da inviare al ser- 
ver. Possiamo così parzializzare i dati e fare 
in modo che ogni client ottenga solo quelli di 
sua competenza. 

• Push: i dati modificati sul client vengono 
inviati al server ed inseriti nella tabella cor- 
retta. 

• SubmitSql: da la possibilità di eseguire query 
SQL direttamente sul Data Base server, usan- 
do ovviamente l'architettura RDA. 

È molto importante sottolineare una cosa: non 
è possibile richiamare il comando Push su una 
tabella di cui non è stato fatto prima il Pulì, e 
questo perchè, senza aver eseguito il Pulì, l'a- 
gente client non potrà tracciare le modifiche 
eseguite su una tabella. L'ordine di esecuzione 
da seguire quando si usa RDA è mostrato in 
figura 3. 





1 


^^^^^H 






■ I 
I Drop 
1 tabelle 
1 locali 


Pulì 

£> A 


Modifiche 


I 

Push dei 1 
dati 1 


^MM^^MMM^^^ta 


Lhh 


jm^ 




J^^ 





Fig. 3: L'ordine di esecuzione dei comandi con RDA 



Se l'ordine non viene rispettato, avremo degli 
errori nel momento in cui cercheremo di sin- 
cronizzare i dati con il server. Se abbiamo delle 
tabelle locali non presenti sul server, per cui 
non abbiamo la possibilità di eseguirne il Pulì, 
ci torna comodo il comando SubmitSql. 



INSTALLAZIONE 

E CONFIGURAZIONE 

Prima di iniziare ad usare RDA però, dobbiamo 
installarne la parte server e configurala. La pro- 
cedura non è immediata e richiede una serie di 
passi che vedremo in questo paragrafo. 
Il primo passo è ovviamente quello dell'instal- 
lazione della parte server. Dopo aver installato 
Microsoft SQL Server 2005, lanciamo il file 
sqlce30setupen.msi localizzato nella cartella 
C:\Programmi\Microsoft SQL Server\90\Tools\ 
Binn\VSShell\Common7\IDE. Il Setup è abba- 
stanza rapido e si completa facilmente in cin- 
que passi. Una volta completato, bisognerà 
configurare i server tools. Di seguito la proce- 
dura completa. 

IFare doppio click sul file ConnWiz30.exe 
presente nella cartella 
C:\Programmi\Microsoft\SQL 
Server\90\Tools\Binn\VSShell\Common7\IDE. 
Verrà avviata la procedura guidata di configu- 
razione di RDA. 




► Welcome to the Configure Web 
Synchronization Wizard 






< 



: 



This wizard helps you: 



* Configure a virtual director/ in Internet Information 

Services (115] aid set permissionfor the directory. 



■Set fi le access permissionsonfolders neededfor 
HTTP data synertran izatìon. 



I~~ Do notshowthisstarting pace a L ;air. 




2 Spuntare la check box "SQL Mobile 
Edition" alla richiesta di che tipo di sotto- 
scrizione vogliamo configurare. 



^ Welcome to the Configure Web Svrichromzal 



Subscriber Type 

Choose the type of Subscriber trat will use this virtui 



Vibici" type of Subscriber will syrscrrorize its data usir-g 

* SQL Server Mobile Esitior 
SQL Server 



► 62 /Settembre 2006 



http://www.ioprogrammo.it 



Remote Data Access H ▼ MOBILE 



311 terzo step ci permette di configurare cor- 
rettamente il server web su cui è installato 
US. Tale server deve essere raggiungibile dal- 
l'esterno (vedi Figura 1). Per le nostre prove 
locali possiamo scegliere il PC di sviluppo su 
cui stiamo lavorando e specificare alla proce- 
dura di creare per noi il sito web. In caso stes- 
simo configurando una applicazione reale, 
possiamo scegliere il nome della macchina su 
cui è installato US ed eventualmente un sito 
web già presente. 



.,,^...,1 ji...i l -.t..i,ri l .i, J ;,' J i»..,ii«ii..ii l -,..,.;..i.^-„.,. l 



Web Server 

Chocse a Web server and either create a ne*' yirtual directory or configure 
an existina virtual directory 



Enterthe nameof the computer running US: 
|HIG-N0TEB00K "*^^— ^^— 



f* Createa ne^virtual directory ^B*- 
r - Configure an esistine virtual directory 



Select the Web s ite in which to create the ne* virtual d i rectory: 






E J) MIG-NOTEBQOMocd computer) 




à-Q Web Sites 




- ■#§ 


^ly.TXHiEfflra ^^_ 


— 3 


+ % 


J: HSHelp 




+ v'| 


I VìrtualServer 




+ : if 


I Printers 





Help 






4 Se scegliamo la prima via, ci verrà chiesto 
di specificare un alias per il sito web (o 
directory virtuale) e la cartella sul file system 
in cui risiederanno i files 



Virtual Directory Information 

Specifysn alias and path for the virtual director/. 



Enterthe alias you wantto use to access this virtual directory, and path for the virtual 
di rectory on the computer running US. 



Alias. 




Mobile DataSync ^^^~™ 


— 1 


Path: 







J\ The path of the virtual directory should be specìfied as a locai path fForexample 
c:\Program Rles}, even if the computer njnning US is a remote computer. 



Help 



Cancel 



5 Se stiamo configurando RDA per la prima 
volta in un sito web, ci verrà segnalato che 
il componente che deve rispondere alle 
richieste provenienti da US (Sqlcesa30.dll) 
non è presente nella directory virtuale. 
Possiamo farlo copiare direttamente dal 
wizard cliccando su Ok. 




6 per rendere sicura la comunicazione tra il 
client ed il server, abbiamo la possibilità di 
crittografare i dati scambiati lavorando sul 
protocollo https. Se abbiamo il certificato, 
possiamo scegliere questa opzione, altrimenti 
dobbiamo usare il normale protocollo http. 



Sgcutg Communications 

Configure Secure Socket-; LjyrT I S S Li rsrcrypted communic* 



s rr-srrsl v;ill fs oìs^;- 



s your virtual directory thraug li 



l~~ R53Lire-:li*rt csrtifissteì. Ussrs without ; ■■sii: : aliti;: giovili t; d-aiied access 



Hejp | 



Cancel 



7 In questo step possiamo scegliere se il 
client ha bisogno di autenticarsi per ese- 
guire la sincronizzazione dei dati. 
L'autenticazione può avvenire in svariati 
modi, ma la trattazione esula dallo scopo di 
questo articolo. Inutile dire che, in un 
ambiente reale, dovremmo scegliere https e 
l'autenticazione. 



«^ 



Client Authenticotion 

Specify thet/peof authenticatioi used when the client connects tothe 
Web server: 



How wiì cliente connect to the Web server wtien aGeessing the virtual directory? 

(* Cliente will connect anonynwusly. A user lameand password will net be required. 
' Cliente will beauthenticated. A user rame and password wi II be required. 



8 



In caso di accesso anonimo, come nel 
nostro esempio, abbiamo la possibilità di 
scegliere con quali credenziali deve essere 
riconosciuto l'utente anonimo appunto. 
Lasciamo questa maschera così com'è e pro- 
cediamo. 



DOVE TROVO 
IL WINDOWS 
MOBILE SDK? 

Il Microsoft Windows 
Mobile 5.0 SDK è 
scaricabile al seguente 
indirizzo web: 
http://www.microsoft.c 
om/downloads/details.a 
spx?familyid=83A52AF2 
-F524-4EC5-9155- 
71 7CBE5D25ED&display 
lang=en ed include gli 
emulatori ed i template 
di Microsoft Visual 
Studio .NET 2005. 



http://www.ioprogrammo.it 



Settembre 2006/ 63 ► 



MOBILE T H Remote Data Access 




E SE HO SQL 
SERVER 2000? 

Sebbene in questo 

articolo si parli di RDA 

con SQL Server 2005 e 

la relativa versione 

Mobile, anche in SQL 

Server 2000 e SQL 

Server CE è possibile 

usare, allo stesso 

modo, RDA. 



AnonymDus Access 

Speci fy the account risedi te establishanonymoLJS access tome virtual 
di recto ry. 






When cliente ccnnectanonymcLisly, NSwill impersonate the following account to access 
the virtual directory: 


User account: 


Chance... 


Password: 


aUNC 


rj The virtual director/ will be used for SQL Server rr>erge replication with 
snapshot share. 








Help <Back Next> 1 


Canoel 







9 in questa maschera del wizard, dobbiamo speci- 
ficare un path condiviso in cui appoggiare le 
tabelle di snashpot. Esse sono riferite alle repliche di 
Data Base, ma la procedura lo richiede e dobbiamo 
obbligatorimente configurarle. 



Snapshot Stia re Access 

Specify the snapshot share on which to set access permissions. 



Enterthe network patti c-f ths 3rsp3hc-t shsre :'f;r sxarrpls V,T = :hire_na™\share): 

Share: 

|V'jnig-notebook'\SnasripotSriare| Browse... 



;\ A snapshot share must alreadyexist.To set access permissions ,you musthave 
administratorprivilegesforthe computer on which the share is locateci. 



Help 



"I /^L'ultima maschera che ci si presenta, riporta 
_L Wun report di quello che abbiamo impostato. 
Se è tutto ok, clicchiamo sul bottone "Finish" ed 
attendiamo che la procedura completi tutte le ope- 



razioni. 



• Create the directory "D:\Webs ":. tI =■■=.-■ .-■": inimediatety 

• Create a virtual director/ immediate^ 

• Copy the ISAPI dll sglcesaiCdirto '□ VWeba' 1 Mobile Data Sync " irnmediater-y 

• Set NTFS permissions immediate!/ 

D:\Web5\MobileData5ync will be created. 

A virtual directory wiH be created with the follo wing optional 

On server MG-NOTEBOOK 

Use 'MobileDataSync'asthe alias. 

Use 'D:\Webs\Mobile-DataSync' as the physical path for the virtual directory 

Lise 'Moti/ttìolis asthe autheriication methodlsj. 

Do not require secure channel 

Set user pennissJons to 'Execute' 

Clienti can use http://MIG-M0TEEJQOK Mot eDataSync :: :tì: ':'. dll asthe 



I ; -'- I 



1"| L'ultima maschera della procedura, ci confer- 
_L ma che tutte le operazioni sono state corretta- 
mente eseguite. Se qualcosa dovesse essere andato 
storto, ci verrà segnalato e sarà possibile usare l'help 
per correggere l'errore. 



V Welcome to the Configura Web Synchronization Wizard 



Configure Web Synchronization 

Click Stop to interrupttheoperation. 






io 



3 Total 
S Success 



Error 
C Warning 



) 



Details: 


| Action 


Status 


Message 




40 Creatingthe phys : = ■:■■=:■-. for the virtù... 


Success 






'40 Creating the virtual directory 


Success 






& Copyingthe ISAPI DLL 


Success 






40 Setting the directory permissions 


Success 






■40 Setting the server agent permissions 


Success 






'40 Setting the snapshot : rectory permissi ... 
'40 Setting the snapshei share permissions 


Success 






Success 






40 Modifying the Virtual Directory configur.. 


Success 




















FiSter v | 


Stop 


Report w 



Una volta eseguiti tutti gli step elencati in questo 
paragrafo, possiamo immediatamente provare a 
vedere se tutto è stato correttamente configurato 
richiamando sul browser il seguente indirizzo: 
http://nome-pc/Mobile 

DataSync/sqlcesa30.dll (dove Nome-PC è nome 
della vostra macchina di sviluppo o del server in cui 
è stato configurato il sito web e MobileDataSync è 
l' alias che abbiamo scelto al passo 4. Se il browser ci 
risponde con la dicitura: "SQL Server Mobile Server 
Agent 3.0" siamo pronti ad usare RDA. La stessa ope- 
razione è consiglabile farla usando browser del 
pocket pc (o dell'emulatore). 



DOWNLOAD 
DEI DATI: PULL 

Come abbiamo visto in figura 3, se dobbiamo lavo- 
rare con RDA, la prima operazione da fare è la il Pulì 
dei dati dal server verso Data Base del dispositivo 
mobile. Essendo una operazione che potrebbe 
richiedere del tempo, per evitare di lasciare l'inter- 
faccia bloccata, è meglio far eseguire la sincronizza- 
zione in un thread separato e notificare, magari 
mediante dei messaggi in una textBox, lo stato di 
avanzamento della sincronizzazione. 
Di seguito il codice per effettuare il Pulì dei dati: 

private void PullDataQ { 
//Pulì delle Tabelle 
InvokeDelegate del = new 

InvokeDelegate(InvokeMethod); 
SqlCeRemoteDataAccess rda = nuli; 

try{ 

foreach (String table in _tablesName) { 



► 64 /Settembre 2006 



http://www.ioprogrammo.it 



Remote Data Access m ▼ MOBILE 



this.Invoke(del, new object[] {"Inizio 

drop tabella " + table}); 
DBHelper.DropTable(table); 
this.Invoke(del, new object[]{"Drop 

tabella " + table + " eseguito"}); 



rda = new 



SqlCeRemoteDataAccess(_ServerUrl, 
DBHelper.ConnString); 



this.Invoke(del, new object[] { "Inizio 

Pulì tabella " + table }); 
rda.Pull(table, "SELECT * FROM " + 

table, _rdaOleDbConnectString, 



RdaTrackOption.TrackingOn); 



this.Invoke(del, new object[] { "Pulì 

tabella " + table + " eseguito" }); 



} 



this.Invoke(del, new object[] { "Procedura di 



Pulì completata" }); 



} catch (SqlCeException sqlCeEx) { 



MessageBox.Show("Si è verificato un errore 

durante la sincronizzazione dei dati. Ripetere 

l'operazione", "Mobile Order", 

MessageBoxButtons.OK, 

MessageBoxIcon.Exclamation, 

MessageBoxDefaultButton.Buttonl); 



} finally { 


rda.Dispose(); 


} 


} 



jtableName è un vettore di stringhe contenente i 
nomi delle tabelle da sincronizzare. Ciclando gli ele- 
menti di questo vettore, richiamiamo come prima 
cosa un metodo del nostro DBHelper (si faccia rife- 
rimento al codice allegato per i dettagli) che esegue 
il Drop della tabella. 

Viene successivamente creata una istanza dell'og- 
getto RD a cui si passa l'uri del sito web che abbiamo 
configurato precedentemente e la stringa di connes- 
sione del Data Base locale. L'ultima operazione è 
quella di eseguire il Pulì vero e proprio dei dati spe- 
cificando i seguenti elementi: 

1. Il nome della tabella di cui eseguire il Pulì 

2. La stringa sql per decidere quali dati della tabella 
scaricare sul client. In questa fase potremmo far 
scaricare sul device solo i dati di competenza di 
uno specifico agente. 

3. La stringa di connessione al Data Base remoto (si 
veda il codice allegato) 

4. Il tipo di tracking che vogliamo eseguire sulla 
tabella. 

Il primo passo è completo. Ora il device può essere 
scollegato ed i dati possono essere modificati. Non ci 
resta che passare alla prossima operazione, ovvero 
l'invio dei dati sul server. Lo faremo con un'operazo- 
ne di push dei dati 



UPLOAD DEI DATI: PUSH 

L'operazione opposta al Pulì dei dati è Push degli 
stessi verso il server centrale. Come per l'operazione 
di Pulì, anche quella di Push può richiedere diverso 
tempo per essere eseguita. Si consiglia quindi di 
farla eseguire in un thread separato. Il codice per 
eseguire il push dei dati è il seguente: 

private void PushDataQ { 
//Push delle tabelle 
InvokeDelegate del = new 

InvokeDelegate(InvokeMethod); 



SqlCeRemoteDataAccess rda = nuli 



try{ 



foreach (String table in _tablesName) { 

this.Invoke(del, new object[] { "Inizio Push 

tabella " + table }); 
rda = new 

SqlCeRemoteDataAccess(_ServerUrl, 
DBHelper.ConnString); 
rda.Push(table, _rdaOleDbConnectString); 
this.Invoke(del, new object[] { "Push tabella 

" + table + " eseguito" }); 

} 

this.Invoke(del, new object[] { "Procedura di 

Push completata" }); 
} catch (SqlCeException sqlCeex) { 

MessageBox.Show("Si è verificato un errore 

durante la sincronizzazione dei dati. Ripetere 

l'operazione", "Mobile Order", 

MessageBoxButtons.OK, 

MessageBoxIcon.Exclamation, 

MessageBoxDefaultButton.Buttonl); 

} finally { 

rda.Dispose(); 



} 



Anche in questo caso, l'operazione si riduce a poche 
righe di codice. Dopo aver creato una istanza di 
RDA, si richiama il metodo Push passando come 
argomenti il nome della tabella e la stringa di con- 
nessione del Data Base server. L'agente client di RDA 
si occuperà di inviare al server solo i record modifi- 
cati dall'ultimo Pulì della stessa tabella. 
Eventualmente, impostando opportuni flag, possia- 
mo tenere anche traccia di eventuali errori di sincro- 
nizzazione. Si veda il box laterale per dei riferimenti 
sul web. 



CONCLUSIONI 

Termina qui la nostra serie sul Mobile. I tasselli per 
creare un'applicazione da zero ci sono tutti. Non vi 
resta che iniziare a sperimentare. 

Michele Locuratolo 




http://www.ioprogrammo.it 



Settembre 2006/ 65 ► 



SISTEMA T ■ Uso di un profiler 



OTTIMIZZIAMO 
IL CODICE CON JRAT 

I PROFILER SONO STRUMENTI MOLTO INTERESSANTI! CHE CONSENTONO DI OTTENERE 
UNA MISURA DELLE PRESTAZIONI PRECISA MENTRE IL SOFTWARE È IN ESECUZIONE. 
SFRUTTANDO QUESTE TECNICHE È POSSIBILE OTTERE MIGLIORAMENTI SIGNIFICATIVI... 





REQUISITI 






Basi di Java. 



§ 



Jrat, un compilatore 
Java 




I profiler sono strumenti software in grado 
di analizzare il comportamento di un'ap- 
plicazione a runtime ed estrarre utili infor- 
mazioni quali il tempo di esecuzione dei 
metodi, l'occupazione di memoria, ecc.. 
Scopo di tali misurazioni è quello di identifi- 
care i "colli di bottiglia" dell'applicazione per 
eseguirne refactoring mirati e ridurre così il 
tempo di esecuzione a tutto vantaggio delle 
prestazioni. 

Il profiler che analizziamo in questo articolo è 
Jrat, pensato per Java ed open source. Jrat 
instrumenta le classi dell'applicazione in 
modo che ogni metodo al principio e al termi- 
ne scriva su un log dei riferimenti temporali. 
L'interfaccia grafica di Jrat permette poi di 
visualizzare tale log sottoforma di un albero 
dove ogni nodo rappresenta una chiamata ad 
un metodo. 

Per ogni metodo sono visualizzate varie infor- 
mazioni tra le quali il tempo di esecuzione 
totale del metodo rispetto al tempo di esecu- 
zione totale dell'applicazione, il tempo di ese- 
cuzione nell'ambito del metodo chiamante, il 
numero di volte che il metodo è terminato 
correttamente o ha sollevato un'eccezione. 
Per utilizzare proficuamente JRat è necessario 
provarlo su un'applicazione vera e propria 
anche se di dimensioni limitate. Scegliamo 
come applicazione d'esempio XS/XXL Sudoku 
disponibile su internet all'indirizzo 
http://sudoku.danidemi.com. Questa è un'appli- 
cazione che permette di giocare a Sudoku su 
griglie da 4x4 sino a 25x25 passando per il 
classico 9x9. 



PARTIRE COI\l JRAT 

Il primo passo è quello di scaricare Jrat dalla 
relativa home page http://irat.sourceforqe.net/ . 
Scaricate sia Jrat che BCEL, offerto nella stes- 
sa pagina di download. Jrat è il profiler vero e 
proprio. BCEL è una libreria Apache necessa- 



Gioco Aiuti Preferenze ? 


BEH 


7 


6 




■!■■ 






1 




5 






3 


2 


S 


3 


■■D 






■■D 


2 


s 


3 


■B 








6 




■■D 








■D 




3 




UMM 


6 


9 










3 


2 






•> 






■" 



Fig. 1: Per i nostri esempi tenteremo di ottimizzare 
l'applicazione del sudoku disponibile all'indirizzo 

http://sudoku.danidemi.com. 

ria a Jrat per l'instrumentazione. 
Salvate il file di Jrat ed eseguite un doppio clic 
sul file appena scaricato. Quando l'applica- 
zione vi chiederà la locazione del file BCEL 
navigate il file system e selezionate il file 
BCEL.jar scaricato insieme a Jrat. Il primo 
passo è quello di instrumentare le classi del- 
l'applicativo per sottoporre ad analisi. Per fare 
ciò selezionare il seguente menù. 

Instrument > Inject Directory Recursively 

Scegliete ora la directory che contiene i file 
.class dell'applicazione, che potete trovare 
nella cartelbin. Lanciamo ora l'applicazione 
specificando i seguenti parametri. 

java com.danidemi. sudoku. gui.Gui 

D] rat. factory = org.shiftone. jrat. provider, tree. 
TreeMethodHandlerFactory 

Utilizziamo normalmente l'applicazione, 
simulando una normale sessione, accedendo 



► 66 /Settembre 2006 



http://www.ioprogrammo.it 



Uso di un profiler ■ T SISTEMA 



a tutte le voci di menù e chiudiamo l'applica- 
zione. Ora sempre da Jrat invochiamo la 
seguente voce di menù. 

Jrat > Open Jrat Output File 

Portarsi nella cartella JratOutput che è stata 
creata allo stesso livello della cartella "bin"che 
ha un nome simile al seguente: 

JratOutput/2006-06-07_PM-l 1-44-02 

Ovviamente il nome della cartella varierà in 
funzione del momento in cui avete fatto gira- 
re l'applicazione instrumentata. Identificate e 
selezionate il file con il seguente nome. 

002_TreeMethodHandler.xrat. 

Si aprirà quindi una finestra con il dettaglio 
del tempo di esecuzione dei vari metodi. I 
metodi "critici" che più occupano tempo sono 
indicati a mo di semaforo da una icona rossa. 



UNA PRIMA 
OTTIMIZZAZIONE 

Facendo qualche prova si può notare, sia 
attraverso i risultati di Jrat, sia con l'esperien- 
za diretta, come la creazione di un nuovo 
schema di gioco sia la funzionalità più lenta. 
Allo scopo di avere un metro di paragone con 
il quale misurare la qualità delle ottimizzazio- 
ni che andremo ad apportare, riapriamo l'ap- 
plicazione instrumentata, impostiamo la 
grandezza della griglia di gioco a 25x25 e per 5 
volte richiamiamo la funzionalità di creazione 
di una nuova griglia, seguita ogni volta dalla 
risoluzione automatica della griglia stessa. 
Apriamo il grafico Jrat. Uno dei metodi che 
impiega più tempo è newGame(). Scorriamo 
l'albero e notiamo che una prima ottimizza- 
zione si potrebbe applicare al metodo 
getDimension(). Il sorgente di 

getDimension() è 



File Window Instmment Help 

Originale. xrat I Qttimizsasione.xrat I Cache, xrat I 



ORoot 

S-O mairi - 991ms 

É-O doNewGame - 12.334ms 

É • buildRadioButton 

H • update - 0,6% 

É • newGrid - 98,7% 

É-*build-98,6% 

El-# getRandomEmptyCell - 8,7% 
É-»build-0,l% 
É-» lockCell 
É-* solve -89,5% 

É-O deduceOnSector - 29,3% 
H-* applyDeducedValues 
É]-# getOriginatingDimension 
É-# possibleValuesAssignableToCell - 29% 




Fig. 2: La schermata di Jrat mostra le prestazioni del- 
l'applicativo. Il metodo doNewGamef) è il più lento 
prendendo ben circa 12 secondi per creare 5 nuove 
griglie di gioco 25x25 

che memorizzi in un attributo di classe le 
dimensioni dell'array. Il costruttore originale, 
qui riportato: 

grid = new CelIValue 

[originatingDimension * 

originatingDimension] 
[originatingDimension * 

originatingDimension]; 

Sarà modificato in modo da memorizzare nel 
nuovo attributo di classe gridLength la 
dimensione dell'array 



private fina 


int gridLength; 




grid = new 


CelIValue 


[originating 


Dimension * 

originatingDimension] 


[originating 


Dimension * 

originatingDimension]; 


gridLength 


= grid.length; 





Sostituiamo inoltre tutte le chiamate a 
getDimensionO con un riferimento alla varia- 
bile gridLenght appena inserita. 



PL 


blic 


int getDimension() { 






return 


grid.length; 


} 



Grid è un array istanziato solamente nel 
costruttore della classe ConcreteGrid. Si 
potrebbe quindi precalcolare la lunghezza 
dell'array ed utilizzare direttamente tale valo- 
re risparmiando l'invocazione al metodo 
get D i mensi o n () . 
Modifichiamo allora il costruttore in modo 



OTTIMIZZAZIONE 
DI GETCELLO 

Analizziamo il metodo getCell() di seguito 
riportato. 

public Integer getCell(int x, int y) { 

checkAccessingCoordinate(x); 
checkAccessingCoordinate(y); 

if(grid[x][y] = = null){ 

throw new 



http://www.ioprogrammo.it 



Settembre 2006/ 67 ► 



SISTEMA T ■ Uso di un profiler 




IllegalArgume 


ntException( 


celi 


" + x + ",' 


+ y 

nuli 


+ " 
is 

"); 


} 






return grid[x 


][y].getVal 


je(); 




} 



L'invocazione di 

checkAccessingCoordinate() pare inutile poi- 
ché il suo unico compito è quello di sollevare 
una IndexOutOfBoundException nel caso si 
cerchi di accedere ad una cella della griglia di 
gioco non esistente, e verrà quindi rimossa. Il 
doppio accesso all'array è inutile, se si memo- 
rizza il risultato del primo accesso per riutiliz- 
zarlo in seguito. Il codice si trasforma. 







CelIVal 


uè celIValue = g 


rid[x][y]; 


if(cellValue = = null){ 








throw new 




IllegalArg 


jmentException("cell " + x + " 


" + y + " 










is 










nuli."); 


} 






return 


celIValue. getVal 


Je(); 



OTTIMIZAZIONE 

DI VALUESOIUSECTORO 

Proviamo ad ottimizzare il metodo valueOn 
SectorO e i metodi simili valueOnRow() e 
valuesOnColumnO che hanno il compito di 
restituire tutti i valori impostati rispettiva- 
mente sulla nel settore, nella riga e nella 
colonna insistenti sulla cella di coordinate x, 



§ ShiftOne JRat Desktop 



File Window Instrument Help 



-Inlxi 



Originale. xrat Ottimizzazione. xrat | Cache. xrat | 



Root 
É-O mah- l,002ms 
É-O doNewGarne - 3,697rins 

É# buildRadioButton - 0,2% 
É-# update- 1,9% 
[=]■■■♦ newGrid - 96,5% 
É-# build - 96,5% 

É-* getRandomEmptyCell - 17% 
É-# build - 0,3% 
É# lockCell 
É-# solve - 78,7% 

É-O deduceOnSector - 25,9% 

Ù3...M =.ni-.kjrìorliirorl^=,liio^ - n 1 O/. 



1 






Fig. 3: Con le ottimizzazioni relativamente semplici descritte nei primi passi si 
ottiene una situazione in cui lo stesso metodo impiega solo all' incirca 3,5 secondi, 
migliorando la situazione iniziale di ben 4 volte. 



y. I tre metodi eseguono un ciclo sulle celle 

della corrispondente zona raccogliendo i 

valori in un Vector(). 

In dettaglio il metodo valuesOnSector(), il più 

complesso. 

public Vector valuesOnSector(int x, int y) 



Vector numbers = new 



Vector(); 



int startX = (x / 

getOriginatingDimension()) 



getOriginatingDimension(); 



int startY = (y / 

getOriginatingDimension()) 



getOriginatingDimension(); 



for (int ix = startX; ix < startX 
+ 

getOriginatingDimension(); ix + + ) { 
for (int iy = startY; iy 
< 

startY + getOriginatingDimension(); iy+ + ) { 

if 
(getCell(ix,iy) != nuli) { 
numbers.addElement(getCell(ix,iy)); 



} 

return numbers; 

} 

Il fulcro di questo metodo è il calcolo delle 
coordinate iniziali di un settore memorizzate 
nelle variabili startX e startY che viene ripetu- 
to ad ogni invocazione. Si noti come tale cal- 
colo ha lo scopo di ottenere partendo da una 
coordinata il valore di partenza del settore che 
contiene la coordinata stessa. 
Prememorizziamo quindi le coordinate di ini- 
zio e fine di un settore all'interno di un array 
di interi. L'indice dell'array sarà la coordinata 
della griglia di gioco di cui vogliamo conosce- 
re le coordinate di inizio del settore in cui è 
contenuta. Ad esempio in un griglia di gioco 
9x9 la cella di indice 3 è compresa nel settore 
che parte dalla cella 2 e termina alla cella 4. 
Quindi l'array dovrà avere all'indice 3 valore 
2. Un altro array potrebbe fornire la coordina- 
ta di fine del settore nel medesimo modo. 
Popoliamo tali array nel costruttore, che 
saranno memorizzati negli attributi di classe 
coordTo StartSectorCoord[] e coordToEnd 
SectorCoord[]. 

Ne approfittiamo per inserire una variabile 
locale ed evitare la doppia chiamata a 



► 68 /Settembre 2006 



http://www.ioprogrammo.it 



Uso di un profiler ■ T SISTEMA 



getCellO all'interno del ciclo. Il sorgente si 
trasforma quindi in questa maniera. 

private final int coordToStartSectorCoord[]; 
private final int coordToEndSectorCoord[]; 
//nel costruttore 

coordToStartSectorCoord = new int[gridLength]; 
for (int i = 0; i < coordToStartSectorCoord. length; 

i + + ) { 

coordToStartSectorCoord[i] = (i / 
originatingDimension) * originatingDimension; 



int startX = coordToStartSectorCoord[x]; 
int endX = coordToStartSectorCoord[y]; 
int endX = coordToEndSectorCoord[x]; 
int endY = coordToEndSectorCoord[y]; 



for (int ix = startX; ix < endX; ix+ + ) { 

for (int iy = startY; iy < endY; iy+ + ) { 
Integer value = getCell(ix, iy); 



glia master. 

Ovviamente se dovesse essere aggiunto un 
valore in una cella facente parte della riga per 
cui si sono posti nella cache insultati, la cache 
deve essere invalidata in modo che in un suc- 
cessivo accesso il calcolo venga nuovamente 
delegato alla griglia mater. 



LA PRIMA 

BOZZA DELLA CLASSE 

Viene implementata la classe Grid. Ci sono 
poi alcune costanti che identificano il dato in 
cache di una colonna, di un settore, o di una 
riga. 

public class CachedGrid extends DelegationGrid 

implements Grid { 
private static final int 

CACHE_NEIGHBOROUD = 3; 
public static int CACHE_ROW = 0; 




public static int CACHE_COLUMN 



1; 



public static int CACHE_SECTOR = 2; 
private Hashtable cache = new 

Hashtable(); 



} 



SFRUTTIAMO 
LA CACHE 

La classe principale dell'applicazione è 
ConcreteGrid che rappresenta la griglia del 
Sudoku e che realizza l'interfaccia Grid. 
Seguendo il design pattern decorator l'appli- 
cazione prevede altre implementazioni di 
Grid che offrono varie funzionalità. 
Per accelerare l'esecuzione dei metodi scri- 
viamo una nuova implementazione di Grid 
che abbia la responsabilità di eseguire il 
caching dei dati forniti dai metodi che resti- 
tuiscono i valori presenti nelle righe, nelle 
celle e nei settori quali valuesOnColumn(), 
valuesOnRowO e valuesOnSector(). Ogni 
volta che uno di questi metodi viene invocato 
esso restituirà sempre lo stesso risultato, a 
patto che nessuna cella sia stata variata nella 
zona di competenza. 

Ecco illustrato il funzionamento della classe. 
Ci sarà un riferimento alla Grid di cui si desi- 
dera effettuare il caching. Alla prima invoca- 
zione di un metodo di accesso alla griglia 
quale valuesOnRow l'esecuzione viene dele- 
gata alla griglia master. Il risultato viene 
memorizzato in una cache implementata tra- 
mite una Hashtable. Alla seconda e alle suc- 
cessive invocazioni il dato viene prelevato 
dalla cache senza delegarne il calcolo alla gri- 



Creiamo una inner class che ci servirà come 
chiave della Hashtable. La chiave è composta 
da tre interi. Il primo identifica se si tratta 
della cache di una riga, di un settore o di una 
colonna. Il secondo intero identifica nei primi 
due casi l'indice della rica o della colonna. Nel 
terzo caso, insieme al terzo intero identifica le 
coordinate superiore sinistre del settore. 

private class CacheKey{ 

private int cache = -1; 
private int cl= -1; 



private int c2 = -1; 



public CacheKey(int cache, 
int ci, int c2) { 
super(); 



this. cache = cache; 



this.cl = ci; 



this.c2 = c2; 



} 



public boolean equals( 



Object o){ 



} 



public int hashCode() { 



In questo caso risulta importante implemen- 



ti ttp: //www. io program mo.it 



Settembre 2006/ 69 ► 



SISTEMA T ■ Uso di un profiler 




tare equalsQ e hashCodeO per avere un utiliz- 
zo corretto della hashtable. In caso di invoca- 
zioni di un metodo che varia il valore di una 
cella, sia cancellandolo sia modificandolo, 
ovviamente il dato in cache per la riga, la 
colonna ed il settore che insistono sulla casel- 
la in questione vanno invalidati. I due metodi 
in questione si occupano di invalidare l'intera 
cache o solo quella dei dati insistenti su una 
cella. 



private void invalidateCache(){ 


cache. clearQ; 


} 


private void invalidateCache(int x, int 


y){ 


cache. remove( ne w 
CacheKey(CACHE_COLUMN, 


x)); 


cache. remove( ne w 

CacheKey(CACHE_ROW, 


y)); 


cache. remove( ne w 
CacheKey(CACHE_NEIGHBOROUD, x, 


y)); 



cache. remove( ne w 

CacheKey(CACHE_SECTOR, 

master. getStartSectorCoord(x), 

master.getStartSectorCoord(y))); 



I metodi che modificano le celle invalidano la 



- S hiftO ne J Rat Desktop 



File Window hstrunnent Help 



^ 



Originale, xrat ] Ottimizzazione. xrat Cache. xrat J 



ORoot 

E O rnain - 2,524rns 
B-O doNewGame - 985, 2ms 
E-* buildRadioButton - 0,2% 
E-* update -7,5% 
E-#newGrid-87,4% 
&■■• build - 87,4% 

B • getRandomEmptyCell - 64% 
B ♦ build - 1,4% 
B ♦ lockCell 
Ò~» solve -21,1% 

B ■■■♦ deduceOnSector - 4,9% 
B ♦ applyDeducedValues 
B"# getOriginatingDimension 
B-# possibleValuesAssignableToCell - 4,5% 
B-O getCell - 1,8% 

| 4 valuesOnNeigborood 

B-O getAssignableValues - 1,4% 
[&■■• getDirnension 
&■■• getOriginatingDimension 
É-O deduceOnColurnns - 8,1% 
SO deduceOnRows - 7,9% 

\ • dear 

B- • getCell 

B • isFilIed - 0,6% 



CI. . . | M. . ■ | 5i. ■ ■ | E. . . | E. .~ E: 



Mi... M.. 



Fig. 4: Inserendo la modifica architetturale del 
caching otteniamo una situazione in cui si passa da 
12 secondi a circa 1 secondo ottenendo un risultato 
davvero utile dal punto di vista dell'utente. 



cache tramite i metodi su esposti dopo aver 
delegato alla Grid decorata l'invocazione del 
metodo. 





public 


void cancelCell(int x. 


nt 


y) { 






super. cancelCell(x, 


y) 








invai idateCache(int 


X, 


int y) 


} 




public 


void clear() { 






super.clearQ; 


invalidateCache(); 


} 




public 


void fillCell(int i, int j, 


int k) { 


super.fillCell(i, j, k); 


invalid 


ateCache(int x, int y) 






} 



Mentre i metodi che restituiscono i valori devono 
prima controllare la cache. Riportiamo l'esempio 
del più complesso valuesOnSector 

public Vector valuesOnSector(int x, int y) 

{ 

int startX = 
master. getStartSectorCoord(x); 
int startY = 
master. getStartSectorCoord(y); 
CacheKey key = new 
CacheKey(CACHE_SECTOR, startX, startY); 
Vector result = 



(Vector)cache.get(key); 



if(result= = null){ 



result = 
super.valuesOnSector(x, y); 



cache. put(key, result); 



} 



return result; 



} 



Lasciamo al lettore il compito di creare gli 
altri metodi. 



CONCLUSIONI 

Rieseguendo ora l'applicativo con Jrat è possi- 
bile notare come le prestazioni siano notevol- 
mente aumentate. Il codice è diventato più 
rapido ma si sono dovute inserire più variabi- 
li, aumentando quindi l'occupazione di 
memoria. Il codice ottimizzato ha la tendenza 
anche a diventare meno leggibile. 
Tuttavia tramite l'uso di un profiler possiamo 
limitare questi interventi ai pochi punti che 
necessitano di ottimizzazione garantendo un 
buon equilibrio tra leggibilità e manutenibi- 
lità e le relative prestazioni. 

Daniele De Michelis 



* 70 /Settembre 2006 



http://www.ioprogrammo.it 



SISTEMA T ■ Java e l'interoperabilità 



JAVA COME PILOTA 
WORD COME MOTORE 

SIAMO ABITUATI A PENSARE A JAVA COME UN MONDO COMPLETAMENTE STACCATO 
DA QUELLO DEI SOFTWARE CHE GIRANO SUI SISTEMI MICROSOFT TUTTAVIA ESISTONO 
SOLUZIONI CHE POSSONO RENDERE I DUE MONDI MOLTO VICINI... 





REQUISITI 



U.MW.UM 



u 



Java, Edipse 



§ 



Java SDK, Edipse, 
jawin-2.0-alpha1.zip, 
barbecue-I. 0.6d.zip 



^a^a 



Tempo di realizzazione 



00 



Siamo abituati a pensare a Java come un 
linguaggio i cui programmi possono 
essere eseguiti su qualsiasi piattaforma. 
Infatti il suo motto è: "write once, run 
everywhere" guadagnandoci la fama di (unico 
forse) linguaggio veramente indipendente dal 
sistema operativo. In questi ultimi anni però 
si sta affermando un nuovo modo di pensare 
alla programmazione nel quale diventa fon- 
damentale che programmi scritti in linguaggi 
diversi riescano a comunicare fra di loro. 
Questo aspetto non è sicuramente una novità 
visto che i Web Services (e non solo) sono nati 
proprio per favorire l'integrazione fra sistemi 
diversi. Uno dei primi e più pubblicizzati 
esempi di questa nuova filosofia si ritrova in 
.NET dove linguaggi diversi (C#, C++, Visual 
Basic) vengono, esattamente come accade in 
Java, compilati producendo un bytecode 
uguale per tutti i linguaggi. 
Fra i vari intenti di .NET c'è anche quello di 
definire un bytecode standard a cui tutti i lin- 
guaggi (compreso forse Java, un giorno), deb- 
bano uniformarsi così da permettere a qual- 
siasi linguaggio di interagire con un program- 
ma .NET (a tal proposito è interessante dare 
un'occhiata a http://www.ikvm.net/). 
Naturalmente questo è un discorso molto 
generico sull'interoperabilità fra i linguaggi; 
quello che invece spesso succede nella realtà 
è che si ha bisogno di interfacciarsi semplice- 
mente con alcuni componenti del sistema 
operativo che possono essere degli eseguibili 
scritti in C o, su Windows, delle DLL o dei ser- 
ver COM. 



DIFFERENZE FRA 
JIUI AND JAWIN 

Java in realtà offre già un modo per interfac- 
ciarsi ad eseguibili C e questa possibilità è 
offerta da JNI (ricordiamoci che Java stesso è 
scritto in C); in Java è già possibile utilizzare 



funzionalità offerte da eseguibili scritti in C e 
quindi anche componenti del sistema opera- 
tivo, putroppo non sempre in modo semplice 
ed immediato. 

In questo contesto trova spazio Jawin, un pro- 
getto opensource ospitato da Sourceforge.net, 
che si occupa di definire un'astrazione per 
l'interazione tra Java e alcuni componenti di 
Windows, quali oggetti COM e DLL Win32. 



UN ESEMPIO 
CONCRETO 

Entriamo nel merito di come utilizzare Jawin 
per interfacciarsi ad un oggetto scriptable 
qualunque. Le classiche operazioni che pos- 
sono essere eseguite su un qualsiasi oggetto 
sono quelle di accedere ai suoi attributi (tra- 
mite metodi get e set) e quello di invocare dei 
metodi. Jawin ci offre una serie di metodi per 
questi scopi. In primo luogo bisogna ricordar- 
si di racchiudere il nostro codice tra le chia- 
mate ai metodi: 

Ole32.CoInitialize(); 

mentre in chiusura dovremo inserire 

Ole32.CoUninitialize(); 

inoltre è buona norma ricordarsi di invocare il 
metodo close() su ogni puntatore ad oggetto 
COM che non viene più utilizzato; il primo 
passo da eseguire è ottenere un puntatore 
all'oggetto stesso identificato dal PROGID che 
nel caso di Office Word per esempio è: 
Word.Application. Il codice è: 

DispatchPtr app = new 

Dispatch Ptr(" Word. Application");. 

Esposte queste premesse possiamo vedere 
quale il metodo principale per il settaggio di 



► 72 /Settembre 2006 



http://www.ioprogrammo.it 



Java e l'interoperabilità H ▼ SISTEMA 



una proprietà di un oggetto: 

public void put(String prop, Object vai) throws 

COMException; 

nel caso del riferimento alla Word Application 
definito prima e denominato app potremmo, 
aiutandoci anche con la documentazione 
msdn ( http://msdn.microsoft.com/office 
/reference/vba/ ), settare la property Visible 
dell'oggetto stesso in modo da rendere visibi- 
le l'applicazione in questo modo 

app.put("Visible", true); 

potremmo leggere la stessa proprietà utiliz- 
zando il metodo: 

public Object get(String prop) throws 

COMException; 

ed in particolare con l'istruzione app.get 
("Visible") che restituisce sempre un oggetto 
di tipo Object a cui bisogna applicare un cast 
in funzione del tipo di dato che ci si aspetta. 
Per quanto riguarda la conversione dei tipi di 
dati da COM a Java si può fare riferimento alla 
documentazione (javadoc) del metodo 
Variant.ReadObjectO; per quanto riguarda 
invece la chiamata a metodi il codice più 
generico e più usato è il seguente: 

public Object invokeN(String meth, Object[] args) 
throws COMException; 

che accetta come parametri il nome del meto- 
do ed un array di oggetti come parametri del 
metodo stesso. Come abbiamo visto ogni rife- 
rimento ad oggetto COM viene mappato da 
Jawin come DispatchPtr. 

Applichiamo le conoscenze fin qui acquisite 
ad un esempio concreto. Se indaghiamo nella 
documentazione msdn ci accorgiamo che 
ActiveDocument è una property dell'oggetto 
Application ma per poter funzionare prima 
deve essere creato un nuovo documento; la 
creazione avviene invocando il metodo Add 
sulla property Documents dell'oggetto 
Application: 

DispatchPtr app = new 

Dispatch Ptr(" Word. Application"); 
DispatchPtr docs = 

( Dispatch Ptr)app.get(" Documents"); 
DispatchPtr doc = 

(Dispatch Ptr)docs.invoke(" Add"); 

Per creare una tabella 4X10 non dobbiamo 



fare altro che ottenere un'area selezionata dal 
documento e convertirla in tabella invocando 
il metodo ConvertToTableO dell'oggetto 
Selection che restituisce un oggetto Table. 

doc.invoke("Select"); 
DispatchPtr win = 

( Dispatch Ptr)doc.get("ActiveWindow"); 
DispatchPtr sei = 

( Dispatch Ptr)win.get("Selection"); 
DispatchPtr table = 

( Dispatch Ptr)sel.invokeN ("Con vertToTable", new 
Object[]{"",new Integer(10),new Integer(4)}); 

L'oggetto table quindi possiede un metodo 
Celi che accetta come parametri gli indici 
delle celle, quindi basta usare due cicli for 
annidati per scorrere le celle dell'intera tabel- 
la. 




for 


(int j = 


1; 


j < 


= 4; 


j + + ) { 






for 


(int i = 


1; 


i < = 


= 10 


, i + + ) { 






Dis 


patchPtr 


celi = 
(Dis 


patchPtr)table.i 
Integer(i) 


nvoke("Cell",new 
new Integer(j)); 














} 


} 



Ottenuto il riferimento alla cella da riempire e 
supponendo che il riferimento sia celi biso- 
gna invocare il seguente metodo: 

cell.Select(); 

celi. Selection. Range. In lineS ha pes. Add Picture() 



MICROSOFT WINDOWS COM PONE NT 



COM è un framework, basato su 
RPC, definito da Microsoft nel 
1993 con lo scopo di permettere 
la comunicazione tra processi. Un 
server COM non è altro che un 
componente software ospitato 
da una certa libreria in Windows 
(DM) con cui si può comunicare 
conoscendo alcuni suoi 
identificatori che si trovano nel 
registro di Windows. I GUID 
(Global Unique Identifier) sono 
dei codici univoci a 128 bit 
utilizzati per identificare un 
componente COM; in particolare 
esso è identificato da un GUID 
chiamato CLSID, ma essendo tale 
codice alquanto difficile da 
ricordare sono stati definiti 
anche i PROGID, della forma 
<Program>.<Component>[.<Versi 
on>]. Esistono anche gli IID che 



identificano le interfacce 
implementate da ogni 
componente. Fra le varie 
interfacce che un componente 
COM può implementare esiste 
anche IDispatch che fornisce dei 
metodi quali GetTypelnfoCount, 
GetTypelnfo, GetIDsOf Names e 
Invoke che permettono di 
ottenere i dettagli dei metodi 
che il componente stesso espone 
e di richiamarli. 

Passando alle dll esse sono una 
implementazione della libreria 
condivisa da parte di Microsoft; 
tali librerie espongono delle 
funzioni che possono essere 
invocate dai vari programmi 
lasciando al sistema operativo, 
fra le altre cose, il compito per 
esempio della gestione in 
memoria di questi componenti. 



http://www.ioprogrammo.it 



Settembre 2006/ 73 ► 



SISTEMA T IH Java e l'interoperabilità 




e passargli la uri dell'immagine da caricare e 
questo lo facciamo con il seguente codice: 

cell.invoke("Select"); 

sei = (DispatchPtr)win.get("Selection"); 

DispatchPtr rangeCell = 

( Dispatch Ptr)sel.get("Range"); 
DispatchPtr shapes = 

(DispatchPtr)rangeCell.get("InlineShapes"); 
createBarcodeImage("123456789a","C:\\ws\\ 

jawinWfile.jpg"); 
DispatchPtr picture = 

( Dispatch Ptr)shapes. in vokeN(" 

AddPicture",new Object[]{ 

new Stri ng("C: \\ws\\jawin\\file.jpg") 

}); 

Come si può notare è stata inserita anche la 
chiamata ad un metodo per la generazione 
vera e propria dell'immagine, che come 
abbiamo accennato in precedenza si serve 
delle potenzialità della libreria barbecue; 
segue il codice del metodo: 

private static void createBarcodelmage 

(String code,String jpgFilename){ 
// Always get a Barcode from the BarcodeFactory 
Barcode barcode; 

try { 

barcode = BarcodeFactory.createCodel28B(code); 
barcode. setBarHeight(70); 
barcode. setBarWidth(l); 



FileOutputStream fos = new 

FileOutputStream(jpgFilename); 
BarcodelmageHandler.outputBarcodeAsJPEGImage 
(barcode, fos); 
catch (Exception e) { 



e.printStackTrace(); 



} 



PRO E CONTRO 

Probabilmente il codice che abbiamo presen- 
tato non è di stesura immediata ma la com- 
plessità sta comunque nel comprendere 
l'Object Model di Word: è questa l'unica diffi- 
coltà introdotta da questa tecnica che offre 
però infinite possibilità di interazione con i 
prodotti di Office. Naturalmente questo arti- 
colo non ha solo lo scopo di mostrare come 
stampare dei codici a barre ma ha la volontà è 
quella di porre in evidenza come si sia affer- 
mato il trend di trovare soluzioni per rendere 
gli innumerevoli linguaggi di programmazio- 
ne sempre meno distanti gli uni dagli altri. E 
legaati al modello delle applicazioni già pre- 
sente nel sistema. L'enorme diffusione del lin- 
guaggio della Sun e la natura open source di 
Jawin rendeno quest'ultimo un'ottima alter- 
nativa ad altre soluzioni pur sempre valide. 



Diego Pansica 



USARE JAWIN CON ECLIPSE 



Dopo aver scaricato dal sito 
http://sourceforge.net/projects/jawi 
nproject il file zip jawin-2.0- 
alphal.zip ed averlo decompresso è 
possibile creare un progetto su 
Eclipse che ci permetta di eseguire 
le demo con facilità. 
Per fare ciò basterà seguire questi 
passi: 




Info 

Builders 

Deployrnent 
':.': ■ ; ate Settinc 

Java Build Path 
ES Java Code Style 
E!- Java Compiler 

Javadoc Locatior 

JSP Compilation . 

Packaging Config 

Project Referenc 

Task Tags 

Validation 



Java Build Path 



& Source | Ti3 project5 | S; Librarie? j *< 
Source folders on build path: 
ELI £3 iawin Add Folder 



I - Allow outp 



Default output f 
j jawin/bin 



Folder name: | demo5| 

Adv-pr : > 



• creare un nuovo progetto Java su 
Eclipse creando una cartella 
denominata bin per l'output ed 
una cartella denominata demos 
per i sorgenti 

• importare l'intera cartella di 
Jawin contenuta nella 
distribuzione di jawin 

• importare le librerie che si 
trovano nella cartella lib e le 
librerie di barbecue 

• copiare il file jawin.dll sotto 
C:\Windows\System32 oppure 
aggiungerlo al path di Windows 

Jawin offre la possibilità di 
interagire con oggetti COM 
scriptable e non; noi ci limiteremo 
ad interagire con un oggetto 
scriptable cioè con oggetto che 
implementa l'interfaccia IDispatch; 



i 
. a 



r*. tn» y**-ùi t ™*,tùl 



in particolare dimostreremo come 
utilizzare Word per stampare una 
serie di codici a barre in un 
determinato layout; Java ci 
permetterà di generare i codici a 
barre a partire da dei codici 
alfanumerici (utilizzando la libreria 
barbecue) mentre Word ci darà 
tutte le potenzialità di paginazione 
e ci eviterà di preoccuparci della 
stampa. 



> 74 /Settembre 2006 



http://www.ioprogrammo.it 



SISTEMA T H Migliorare le proprie tecniche di sviluppo 



FACILITARE IL DEBUG 
CON I VISUALIZER 

NON TUTTI SANNO CHE VISUAL STUDIO 2005 OFFRE POSSIBILITÀ DI PERSONALIZZAZIONE 
PRATICAMENTE INFINITE. IN QUESTO ARTICOLO ILLUSTREREMO COME MIGLIORARE 
IL DEBUG DI STRUTTURE PROPRIETARIE, UTILIZZANDO CONTROLLI SPECIFICI 




REQUISITI 



WM.i.WlM-MU.1 

.NET Framework 2.0, 
' Ot(c-sharp) 



9 



Windows 2000 o 
superiori. Visual Studio 
2005, .NET Framework 
2.0 






! .1 



Tempo di realizzazione 



Chi sviluppa sa benissimo che la fase di 
debug è fondamentale, necessaria per 
scovare e correggere tutti gli eventuali 
errori che abbiamo inserito nel codice. Le 
interfacce utente degli ambienti di sviluppo 
moderni ci vengono in aiuto, fornendoci una 
serie di strumenti grazie ai quali possiamo 
esaminare i valori delle variabili e lo stato 
degli oggetti in corrispondenza dei break- 
point che abbiamo impostato. Visual Studio 
2005 non può essere da meno. Il menu Debug 
disponibile nell'IDE permette di attivare tutta 
una serie di finestre dedicate al debug, che ci 
permettono di controllare per esempio l'elen- 
co dei breakpoint impostati, di vedere il con- 
tenuto delle variabili definite nello scope cor- 
rente, di consultare lo stack e i thread in ese- 
cuzione. 

.NET ci dà però una marcia in più, consenten- 
do a ciascuno di noi di sviluppare speciali 
visualizzatori associati ad un particolare tipo 
di oggetto .NET. Tali visualizzatori sono 
comunemente chiamati visualizer. È così pos- 
sibile creare visualizer specifici per le strin- 
ghe, per le immagini, per gli array, per i nostri 
business object ed in generale per qualsiasi 
oggetto .NET ci interessi. Il visualizer è chia- 
mato in causa esclusivamente durante il 
debug della nostra applicazione, ed in diversi 
contesti: quando spostiamo il puntatore del 
mouse sopra una variabile il cui tipo è quello 
previsto dal visualizer, oppure quando la stes- 
sa variabile appare in una delle finestre di 
Visual Studio 2005 dedicate al debug (Autos, 
Locals, Watches, etc). 

Lo scopo di un visualizer è quello di fornire 
un'interfaccia per esaminare l'oggetto, 
migliore rispetto a quanto prevede FIDE, che 
per default ci fa esplorare l'intera gerarchia 
delle proprietà usando un controllo che ci 
ricorda la TreeView. 

In questo articolo vedremo come creare un 
visualizer da zero, fornendo alcuni spunti 
interessanti per poterlo migliorare in seguito. 



CREARE PASSO PASSO 
IL NOSTRO PRIMO 
VISUALIZER 

Possiamo creare un visualizer per qualsiasi oggetto 
.NET, creato con qualsiasi linguaggio managed. In 
questo articolo, vedremo come creare un visualizer 
specifico per la classe ArrayList. Ogni volta che nel 
nostro codice comparirà un oggetto di questo tipo, 
potremo utilizzare il nostro visualizer per vederne il 
contenuto o, addirittura, per poterlo modificare in 
debug. Passiamo alla pratica. Iniziamo innanzitutto 
con la creazione di un nuovo progetto. Apriamo 
Visual Studio 2005, andiamo sul menu File/New e 
poi clicchiamo sulla voce Project. Selezioniamo 
nella parte destra il tipo di progetto Class Library, 
chiamiamolo IoProgmmmoCustomVisualizer e con- 
fermiamo il tutto cliccando sul pulsante Ok. 
Rinominiamo la classe con il nome ArrayList 
Visualizer. A questo punto è necessario aggiungere 
un riferimento alla libreria Microsoft. 
VisualStudio.DebuggerVisualizers. Possiamo farlo 
selezionando il nodo References raggiungibile 
all'interno del progetto IoProgrammo 
CustomVisualizer, cliccando con il pulsante destro 
e selezionando la voce Add Reference. Nella finestra 
di dialogo è sufficiente ricercare il file all'interno 
della scheda denominata .NET. Aggiungiamo un 
riferimento anche al file System.Windows.Forms, in 
modo da poter usare le Windows Forms nel nostro 
visualizer ed utilizzare classi come la MessageBox. 
Fatto questo, possiamo tornare al codice della 
nostra classe Array ListVisualizer. Assicuriamoci 
innanzitutto di referenziare attraverso l'istruzione 
using tutti i namespace che ci serviranno nel codice: 

using System; 

using System. Collections; 

using System.Windows.Forms; 

using Microsoft.VisualStudio.DebuggerVisualizers; 

In secondo luogo, la dichiarazione della nostra 
classe deve comparire come segue. 

namespace IoProgrammoCustomVisualizer 



»> 76 /Settembre 2006 



http://www.ioprogrammo.it 



Migliorare le proprie tecniche di sviluppo H T SISTEMA 



public class ArrayListVisualizer : 

DialogDebuggerVisualizer 
{ } 



} 



La classe ArrayListVisualizer eredita direttamente 
dalla classe DialogDebuggerVisualizer. 
Quest'ultima classe mette a disposizione tutta l'in- 
frastruttura .NET necessaria per la creazione del 
visualizer. Giunti a questo punto, buona parte del 
lavoro è fatto. Ci basta fare l'overloading del metodo 
Show() per poter avere un visualizer funzionante. Il 
secondo parametro del metodo Show() è il più inte- 
ressante, perché è attraverso questo che riusciremo 
ad avere un riferimento all'oggetto di cui stiamo 
facendo il debug. Il codice sottostante mostra un 
semplice esempio di come implementare il metodo 
Show(): 

protected override void Show 
(IDialogVisualizerService windowService, 

IVisualizerObjectProvider objectProvider) 

{ 

ArrayList Ist = 

(Array List)objectProvider.GetObject(); 
MessageBox.Show(lst.Count.ToStringO); 



Attraverso il metodo GetObjectfJ esposto dalla clas- 
se IVisualizerObjectProvider, otteniamo una copia 
dell'oggetto che ci interessa debuggare, nel nostro 
caso l'Arraylist. Nel semplice esempio qui sopra, 
visualizziamo semplicemente il numero di elementi 
contenuti nell 'ArrayList e nulla di più. Sebbene sia 
un caso estremamente semplice, rende l'idea e 
descrive la struttura minima per realizzare un visua- 
lizer funzionante. All'interno del metodo Show() 
possiamo scrivere tutto il codice che ci serve, come 
mostrare una Windows Form: ne parleremo più 
avanti in questo articolo. Adesso vediamo come 
testare il visualizer e controllare che tutto funzioni 
correttamente. 



poi rimosso nella versione definitiva: 

public static void TestShowVisualizer(object 

objectToVisualize) 

{ 

VisualizerDevelopmentHost vHost = new 
Visual izerDevelopmentHost(objectToVisualize, 

typeof (ArrayListVisualizer)); 
vHost.ShowVisualizer(); 
~ 

Il parametro in ingresso al metodo rappresenta l'og- 
getto che vogliamo debuggare. Per testare il visuali- 
zer, non dobbiamo fare altro che chiamare questo 
metodo: tale operazione scatenerà l'esecuzione del 
metodo ShowfJ descritto precedentemente. 
Compiliamo quindi la classe ArrayListVisualizer 
per ottenere l'assembly pronto per l'uso. 
Aggiungiamo un nuovo progetto Windows 
Application e chiamiamolo TestVisualizer: questo 
sarà il nostro piccolo progetto di test. Visual Studio 
2005 crea automaticamente una Windows Form 
completamente vuota, alla quale aggiungiamo un 
Button chiamato btnCreaArraylist e gestiamone 
l'evento Click: qui possiamo semplicemente creare 
un oggetto ArrayList ed aggiungere un po' di ele- 
menti. Ad esempio, prendiamo in considerazione 
seguente codice: 

private void btnCreaArrayList_Click(object 

sender, EventArgs e) 

{ 

ArrayList Ist = new ArrayList(); 

for (int i = 0; i < 100; i+ + ) 

Ist.Add(i); 
ArrayListVisualizer.TestShowVisualizer(lst); 



MessageBox.Show("Esecuzione terminata!"); 



} 



Il codice qui sopra crea una nuova istanza di 
ArrayList, al quale aggiungiamo semplicemente i 
primi 100 numeri interi. Notare la linea [6], nella 
quale non facciamo altro che chiamare in causa il 
visualizer, usando il metodo TestShowVisualizer, 
passandogli come parametro l'oggetto Ist, che non è 




TESTIAMO IL VISUALIZER 
APPENA CREATO 

Abbiamo detto prima che il visualizer appare quan- 
do, durante il debug, spostiamo il puntatore sopra 
l'oggetto interessato, oppure quando l'oggetto stes- 
so compare nelle finestre di debug di Visual Studio 
2005. Per poter attivare questo meccanismo, dob- 
biamo decorare la classe ArrayListVisualizer con un 
attributo, che vedremo successivamente. Per ades- 
so, la cosa ottimale è testare il nostro visualizer attra- 
verso un metodo statico TestShowVisualizer, da 
aggiungere alla classe ArrayListVisualizer, che verrà 



LA SERIALIZZAZIONE IN .NET 



La serializzazione è una tecnica 
utilizzata frequentemente in 
.NET, e consiste nel persistere la 
struttura e lo stato di un oggetto 
managed in un formato standard 
XML. Tale conversione può essere 
controllata da una serie di 
attributi che, applicati a dovere 
sulle classi e sulle proprietà, ci 



permettono di decidere la 
struttura del documento XML ed 
i nomi dei tag. Su MSDN è 
pubblicato un documento 
aggiornato al Framework 2.0 che 
descrive nel dettaglio come 
usare questi attributi: 
http://msdn2.microsoft.com/en- 
us/library/2baksw0z.aspx. 



http://www.ioprogrammo.it 



Settembre 2006/ 77 ► 



SISTEMA T I Migliorare le proprie tecniche di sviluppo 




nient' altro che l'ArrayList che vogliamo debuggare. 
Per controllare meglio il flusso del codice, possiamo 
anche impostare un breakpoint alla linea [6] . Dopo 
aver compilato tutta la soluzione, avviamo il proget- 
to TestVisualizer, clicchiamo sul bottone ed aspettia- 
mo che .NET faccia il resto. Se abbiamo fatto tutto 
correttamente, dovremmo veder comparire una 
MessageBox che mostra il numero di elementi nel 
nostro ArrayList, a dimostrazione del fatto che il 
visualizer è stato eseguito correttamente. Ecco il 
nostro primo custom visualizer! Ora non ci resta che 
migliorarlo e renderlo un po' più utile. Non dobbia- 
mo fare altro che tornare al progetto class library 
IoProgrammoCustom Visualizer e modificare il 
metodo ShowQ e decidere cosa vogliamo fargli fare. 



IL NAMESPACE MICROSOFT. 
VISUALSTUDIO.DEBUGGERVISUALIZERS 



Scrivere un visualizer significa 
prima di ogni altra cosa lavorare 
con classi contenute nel 
namespace Microsoft.Visual 
Studio.DebuggerVisualizers, che 
contiene l'implementazione delle 
classi e delle interfacce 
necessarie, come Dialog 



DebuggerVisualizer che è la 
classe dalla quale il nostro 
visualizer deve ereditare. Potete 
avere maggiori informazioni 
partendo dall'indirizzo 
http://msdn2.microsoft.com/en- 
us/librarv/microsoft.visualstudio.debu 



ggervisualizers.aspx. 



UTILIZZARE UNA 
WINDOWS FORM NEL 
NOSTRO VISUALIZER 

Una cosa che potrebbe tornare molto comoda è 
creare una normale Windows Form che possa in 
qualche modo mostrare ogni singolo elemento con- 
tenuto nell 'ArrayList. Possiamo pensare ad esempio 
di utilizzare uno dei controlli .NET che meglio si 
adattano in contesti di questo tipo, come una sem- 
plicissima ListBox. 

Non dobbiamo fare altro che aggiungere una 
Windows Form (che chiamiamo ArrayList Content 
Form) nel progetto IoProgrammo CustomVisualizer, 
posizionare all'interno di essa una ListBox, chia- 
mandola lstArrayListContent, ed utilizzarla all'inter- 
no del metodo Show(). 
Il codice apparirà come di seguito: 

protected override void Show 
(IDialogVisualizerService windowService, 

IVisualizerObjectProvider objectProvider) 

{ 

ArrayList Ist = 

( Array List)objectProvider.GetObject(); 
ArrayListContentForm frm = new 

Array ListContentForm(); 
frm. Array ListToView = Ist; 
windowService. ShowDialog(frm); 



} 



Il codice qui sopra non fa altro che inizializzare il 
form, ottenere un oggetto di tipo ArrayList e visua- 
lizzare la Windows Form attraverso il metodo 
ShowDialog esposto dalla classe IDialog 
VisualizerService. Quello che resta da fare è imple- 
mentare qualche linea di codice anche sulla 
Windows Form. Innanzitutto ci serve una proprietà 
custom ArrayListToView, che viene utilizzata nel 
metodo Show() per il passaggio di parametri. In 
secondo luogo, gestiamo l'evento Load della nostra 
Windows Form per attivare il databinding tra 
l'ArrayList e la ListBox, passando attraverso un 
oggetto BindingSource, raccomandato ogniqual- 
volta si faccia databinding con .NET 2.0: 

private void ArrayListContentForm_Load(object 

sender, EventArgs e) 

{ 

bsSource.DataSource = _arrayListToView; 
this. lstArrayListContent. DataSource = bsSource; 
~ 

Giunti a questo punto, possiamo ricompilare la 
soluzione e provare ad eseguire nuovamente il pro- 
getto. Il visualizer questa volta fa una cosa molto 
diversa, e molto più utile: sullo schermo appare la 
Windows Form che abbiamo appena creato, che ci 
mostrerà il contenuto del nostro ArrayList. Questo 
non solo ci permette di dare un'occhiata 
all'ArrayList in fase di debug, ma ci apre la strada per 
creare nuove interessanti funzionalità, come il per- 
mettere la modifica dell'ArrayList stesso. Per fare 
questo, però, non dobbiamo più usare il metodo di 
test TestShowVisualizer, ma dobbiamo andare un 
po' più in là, sfruttando appieno l'integrazione offer- 
ta da Visual Studio 2005. 



DEPLOY E COMPLETA 
INTEGRAZIONE DEL 
NOSTRO VISUALIZER 

Il visualizer in realtà offre molto di più rispetto a 
quanto abbiamo visto finora. La vera potenza di un 
visualizer sta nella sua piena integrazione con l'am- 
biente di sviluppo, cosa che finora non abbiamo 
preso in considerazione. Per poterlo veramente 
sfruttare al 100%, dobbiamo decorare la classe 
ArrayListVisualizer con un attributo che fornisce 
ulteriori informazioni riguardanti il visualizer che 
abbiamo sviluppato. L'attributo in questione è 
DebuggerVisualizerAttribute, e viene utilizzato nel 
modo seguente: 

[assembly: 

System. Diagnostics.DebuggerVisualizerAttribute( 



»> 78 /Settembre 2006 



http://www.ioprogrammo.it 



Migliorare le proprie tecniche di sviluppo H T SISTEMA 



typeof(IoProgrammoCustomVisualizer. Array List 

Visualizer), typeof(VisualizerObjectSource), 
Target = typeof(ArrayList), Description = "Visualizer 

per ArrayList")] 

L' attributo DebuggerVisualizerAttribute 
decora la classe ArrayListVisualizer, impo- 
stando per esempio una descrizione e comu- 
nicando a .NET il tipo al quale si associa il 
visualizer stesso: questo è lo scopo del para- 
metro Target. Dopo aver ricompilato l'intera 
soluzione, possiamo tranquillamente distri- 
buire il visualizer, che è contenuto nell'as- 
sembly ArrayListVisualizer.dll. È sufficiente 
copiare questo file nella directory 
\Documenti\Visual Studio 2005\Visualizers 
per poter utilizzare il visualizer in modo 
molto più veloce di quanto abbiamo fatto 
finora. Se avete copiato l'assembly nella 
directory indicata, chiudete e a riaprite FIDE. 
All'avvio, Visual Studio 2005 carica tutti i 
visualizer contenuti in \Documenti\Visual 
Studio 2005\ Visualizers, compreso il nostro 
ArrayList Visualizer. Dal momento che non 
vogliamo più utilizzare il metodo 
TestShowVisualizer, possiamo tranquilla- 
mente cancellare la linea [6] che usava il 
metodo TestShowVisualizer. Il codice che ci 
serve è il seguente: 



private 


void btnCreaArrayList 


_Click(object 

sender, EventArgs 


e) 


{ 




ArrayList Ist = new 


ArrayList(); 






for (int i = 


= 0; i < 100; i++) 




Ist.Add(i); 




MessageBox.Showf 


Esecuzione 

terminata! 


"); 


} 



Impostiamo il breakpoint alla linea [6] , che adesso 
contiene la MessageBox ed eseguiamo il progetto. 
Quando entriamo in modalità di debug e l'esecuzio- 
ne del codice si interrompe, spostiamo il puntatore 
del mouse sopra l'oggetto lst: Visual Studio 2005 
mostra un piccolo tooltip che mette in evidenza 
l'oggetto, permettendoci di esplorarlo come solito. 
Questa volta però nel tooltip vediamo anche una 
piccola icona: una lente di ingrandimento. 
La presenza di questa icona indica che a questo tipo 
di oggetto è associato un visualizer. Se la clicchiamo, 
non facciamo altro che attivare il nostro 
ArrayListVisualizer, esattamente come accadeva 
prima, ma senza dover scrivere codice dedicato al 
testing e soprattutto in modo molto più integrato, 
anche in virtù del fatto che il visualizer è disponibi- 
le, come dicevamo prima, in tutte le finestre di 
Visual Studio 2005 dedicate al debug (Watches, 



Autos e così via.). Quello che abbiamo visto è la 
modalità migliore per usare un visualizer, ed è la 
stessa modalità con la quale nostro visualizer verrà 
utilizzato dagli altri sviluppatori se decidessimo di 
distribuirlo. Se tutto quello che volevamo era creare 
un visualizer, potremo fermarci qui ma noi però 
vogliamo andare oltre, e permettere la modifica del- 
l'oggetto che stiamo debuggando. 



COMPLETARE IL 
VISUALIZER: MODIFICARE 
L'ARRAYLIST IIU DEBUG 

In questo momento, abbiamo costruito un 
visualizer funzionante in tutto e per tutto. 
Quando entriamo in modalità debug, il visua- 
lizer ci permette di esaminare il nostro ogget- 
to, ma senza poterlo modificare. Supponiamo 
di voler fare un ulteriore passo in avanti, cioè 
di permettere allo sviluppatore di avere più 
controllo: magari vorrebbe svuotare comple- 
tamente l'ArrayList. Come possiamo imple- 
mentare questa nuova funzionalità? Non dob- 
biamo fare altro che modificare l'implemen- 
tazione della Windows Form, per esempio 
aggiungendo un Button (chiamato btnClear 
Allltems) dedicato a questo scopo: 

private void btnClearAIIItems_Click(object sender, 

EventArgs e) 

{ 

_arrayListToView.Clear(); 
bsSource.ResetBindings(false); 
~ 

Quando lo sviluppatore cliccherà il Button, il 
contenuto dell'ArrayList verrà completamen- 
te eliminato. La seconda linea contenuta pro- 
voca il refresh della ListBox. E se invece voles- 
simo metterlo in condizione di modificare 
uno ad uno ogni elemento dell'ArrayList? 
Sarà sufficiente gestire l'evento Selectedlndex 
Changed della ListBox e visualizzare l'ele- 
mento selezionato in una TextBox, così da 
poterne modificare il valore: 

private void 

lstArrayListContent_SelectedIndexChanged(object 
sender, EventArgs e) 



if (IstArrayListContent. Selectedlndex 



-1) 
retu rn ; 



int number = 

(int)_arrayListToView[lstArrayListContent.S 
electedlndex]; 
txtSelectedltem.Text = number. ToStringQ; 




http://www.ioprogrammo.it 



Settembre 2006/ 79 ► 



SISTEMA T I Migliorare le proprie tecniche di sviluppo 




All'evento Validating della TextBox, tentiamo 
di convertire in intero ciò che l'utente ha 
scritto e, se è possibile, aggiorniamo 
l'ArrayList con il nuovo valore. Manca ancora 
un piccolo particolare importante, che fino ad 
ora abbiamo omesso. All'interno del codice 
del visualizer gestiamo un'istanza di ArrayList 
che è una copia di quella contenuta nel codi- 
ce debuggato: la chiamata al metodo 
GetObjectO nel metodo Show() serve proprio 
a trasferire l'oggetto da un contesto verso l'al- 
tro. Quando lo sviluppatore chiude la 
Windows Form, dobbiamo fare l'operazione 
esattamente contraria, ovvero restituire al 
codice del progetto di test l'ArrayList even- 
tualmente modificato. Questa operazione è 
facilmente ottenibile attraverso il metodo 
ReplaceObject esposto dalla classe IVisualizer 
ObjectProvider: 

if (res == DialogResult.OK) 

{ 

ObjectProvider. ReplaceObject(lst); 



} 



In questo modo, se la Windows Form viene 
chiusa con il Button Ok, trasferiamo l'istanza 
dell'ArrayList che viveva all'interno del visua- 
lizer al codice chiamante, che nel nostro caso 
si tratta del piccolo progetto di test ma che in 
realtà sarà la nostra applicazione reale che 
stiamo sviluppando. Possiamo testare queste 
nuove funzionalità semplicemente rilancian- 
do l'esecuzione del progetto di test: al 
momento dell'attivazione del visualizer, pos- 
siamo modificare l'ArrayList come meglio cre- 
diamo, utilizzando i nuovi controlli che abbia- 
mo posizionati sulla Windows Form. Se chiu- 
diamo la form con il Button Ok, l'ArrayList 
che abbiamo modificato nel visualizer sosti- 
tuisce l'ArrayList del progetto di test, rappre- 
sentato dalla variabile lst. 
Questa è la vera potenza di un visualizer, 
ovvero avere l'assoluta capacità di manipolare 



un oggetto in debug, esattamente come suc- 
cede con variabili value-type, ma con tipi più 
complessi. 



CREARE UHI VISUALIZER 
PER I NOSTRI BUSINESS 
OBJECT 

In questo articolo abbiamo descritto come 
creare un visualizer per una classe .NET stan- 
dard come l'ArrayList. Come è facile immagi- 
nare, possiamo applicare le stesse logiche 
descritte in questo articolo con qualsiasi 
oggetto, compresi i business object apparte- 
nenti al domain model delle nostre applica- 
zioni. Costruire un visualizer è tanto più utile 
quanto più i nostri oggetti sono riutilizzabili: 
se stiamo costruendo un software di fattura- 
zione, ad esempio, potremmo pensare di rea- 
lizzare visualizer per oggetti del domain 
model come clienti, fatture o prodotti: duran- 
te lo sviluppo del software, tali visualizer ci 
consentiranno una maggior intuitività nel 
debug, verificando velocemente che gli ogget- 
ti siano nello stato che ci si aspetta, e magari 
correggendo i valori di alcune proprietà. 
L'unico requisito richiesto per sviluppare un 
visualizer per un certo tipo di oggetto è che 
tale oggetto sia serializzabile. La serializzazio- 
ne è una tecnica piuttosto comune in .NET, e 
consiste nel rappresentare la struttura e lo 
stato di un oggetto attraverso XML. Queste 
consente il trasferimento dell'oggetto stesso 
da un contesto all'altro, da un'applicazione 
all'altra, e così via. Molte classi .NET sono 
naturalmente serializzabili, come l'ArrayList 
di cui abbiamo parlato prima. Dobbiamo 
quindi assicurarci di poter serializzare i nostri 
business object, decorando la classe con l'at- 
tributo [Serializable], e così per la proprietà 
esposte dall'oggetto stesso. Potete trovare 
maggiori informazioni sulla serializzazione 
nel box a lato. 



I DUE ASPETTI DI URI VISUALIZER: 
ÌE» DEBUCGER E DEBUGCEE 



Quando si implementa un 
visualizer, occorre considerare 
che stiamo lavorando con il 
codice proveniente da due 
processi diversi: il codice del 
debugger (debugger side, che è il 
visualizer) ed il codice che invece 
viene debuggato (debuggee side, 
che è la nostra applicazione). 
Capire questa separazione è 



molto importante, perchè 
dobbiamo sempre tener presente 
che gli oggetti nel visualizer 
sono delle copie rispetto a quelle 
che girano nell'applicazione 
debuggata. Questo è il motivo 
principale per cui usiamo il 
metodo ReplaceObject, che 
internamente utilizza la 
serializzazione. 



CONCLUSIONI 

Sono ormai lontani i tempi in cui creare un 
software significava aver a che fare con sem- 
plici variabili di tipo int, float o string. Oggi la 
OOP dà enormi potenzialità, ma d'altro canto 
ha aumentato significativamente la comples- 
sità degli oggetti con i quali lavoriamo. I 
visualizer di Visual Studio 2005 ci permettono 
di debuggare intuitivamente e con più sem- 
plicità il nostro codice. 

Liborio Igor Damiani 



► 80 /Settembre 2006 



http://www.ioprogrammo.it 



SISTEMA T ■ Meno righe di codice con "My' 



IL NAMESPACE MY 
SEMPLIFICA LA VITA 

IN QUESTO ARTICOLO ILLUSTREREMO ALCUNE CARATTERISTICHE DEL NUOVO 
FRAMEWORK 2.0 CHE CONSENTONO DI ACCEDERE RAPIDAMENTE A INFORMAZIONI 
DI SISTEMA ALTRI PERCORSI DI PROGETTO, SENZA TROPPE COMPLICAZIONI... 




REQUISITI 



■jj.l.».JAJ,i., 

.NET Framework 2.0, 
basi di visual Basic 



9 



Windows 2000/XP. 
Visual Basic.NET 2005 




Microsoft Visual Basic 2005 introduce 
il nuovo namespace My, grazie al 
quale lo sviluppatore può accedere 
in modo rapido ad un gruppo di classi impor- 
tanti relative a: il computer su cui l'applica- 
zione è in esecuzione, l'utente che la sta ese- 
guendo, l'applicazione stessa, i form dell'ap- 
plicazione ed a qualsiasi Web service associa- 
to. Nel precedente articolo abbiamo analizza- 
to in dettaglio l'oggetto My. Computer che 
permette di accedere alle informazioni relati- 
ve al computer sul quale è installata l'applica- 
zione, in questo articolo porteremo a termine 
la trattazione descrivendo alcuni altri oggetti 
messi a disposizione dal namespace My. 



L'OGGETTO 

MY. APPLICATION 

L'oggetto My.Application fornisce informa- 
zioni sull'applicazione in esecuzione, come il 
percorso, il titolo, la versione, la nazionalità e 
la modalità di autenticazione dell'utente. 
L'oggetto My.Application espone un buon 
numero di proprietà e metodi. 
Analizziamone alcuni. 

L'oggetto Info, permette di ottenere versione, 
percorso, titolo, descrizione, working set, ed 
altre informazioni sull'assembly dell'applica- 
zione. La maggior parte delle informazioni 
restituite dall'oggetto Info, sono raggiungibili 
per mezzo della finestra di dialogo: 
Informazioni assembly 



uni ESEMPIO 
DI DIALOGO 

1 Selezioniamo il nostro progetto di prova, 
nella finestra Esplora soluzioni e dal menu 
a tendina che si ottiene cliccando con il tasto 
destro del mouse, sulla nostra applicazione, 



selezioniamo la voce: Proprietà 




Bum Hepot U lutti Wl -Sf-rvpr HrpwUig 



. [tu mcrth Jota P«4 r.*fc you nhw *c-j nwd to MJN, 
± VtfKXt Vimml VuiVi le«ii *>yatrfn lc*d Imi U - 
» ZÙ: i J *V GM1 - Ito *W» «fcb «M hand^ rWcrOnq. 

flato Br rtwfii-rrnn itti MJI ht-tvrt ,1WIS 

O.^HVi r.'-Htt fi*F^rtiirlvnTnr*.ij*niJitviw^. 

L •jtff ntt, WS fi a krt nUr* ttafl |uft (hi .ML I 

" ;,Ahf.«rt*r*HAm1IY«'rtrffrmmwliiw*'^3 
*rm rirtfiflUu 4ndnM*M4Mc <f T-K&, Wd itoti. 
SQl km XDOS XML tmipurl. cwcid iim ImiuIIiihi, ... 
D» tTiH;M flHT - Th» ma*, Xt*i Pitti «tonai 
jp*d «rd unopad H cc4urrn. HrjCMW •> cptoon 
iQt, Hi Ibjn Par ?aNr ehm durgn. 

"-- e rtffi m Tiitimmr n TrrfTiiti 



k 



2 A questo punto, viene visualizzata la fine- 
stra delle proprietà con la scheda di 
default Applicazione. Nella scheda 
Applicazione clicchiamo sul pulsante 
Informazioni assembly. . . 





ine; jlMfA 




Piattaforma: JN/A 


v| 


ibly: 




Spazio dei nomi di primo livello: 




SABBISI 




WindowsApplicationl 




razione: 




Icona: 




; Windows 


V 


(Icona predefinita) 


-c 


□ : 










V. 


■Otri', <!,-!!: :■;: ^sfSiòK . .. 


arnework applicazione 

ramework applicazione Windows 
stili di visualizzazione XP 
ì istanza singola 
■ly.Settings alla chiusura 




k 









3 Così facendo, viene visualizzata la finestra 
di dialogo Informazioni assembly con le 
informazioni relative all'applicazione 







i - l 


HI 




LM. 






**■**: OAA 




Ntadn: '"-■kJII 

nutD: :«2òdfJ6-Tf]f-*al*dS.]T#««Mi* 



► 82 /Settembre 2006 



http://www.ioprogrammo.it 



Meno righe di codice con "My' 



T SISTEMA 



Le informazioni esposte dall'oggetto Info, 
tipicamente si visualizzano nella classica 
finestra di dialogo about delle applicazioni 
Windows Form. Il codice seguente mostra in 
un TextBox una serie di informazioni ricavabi- 
li dall'oggetto Info: 

Dim Informazioni As String = "" 

'Visualizza il nome dell'applicazione. 
Informazioni = Informazioni & "Nome:" & 

My.Application.Info.AssemblyName & vbCrLf 

'Permette di visualizzare il nome della società 

'associato all'applicazione. 

Informazioni = Informazioni & "Società:" & 

My.Application.Info.CompanyName & vbCrLf 

'Permette di visualizzare le informazioni sul 
'copyright associate all'applicazione. 
Informazioni = Informazioni & "Copyright:" & 

My.Application. Info. Copyright & vbCrLf 

'Permette di visualizzare la descrizione associata 
'all'applicazione. 
Informazioni = Informazioni & "Descrizione:" & 

My.Application. Info. Description & vbCrLf 

'Permette di visualizzare la directory in cui è 
'memorizzata l'applicazione. 
Informazioni = Informazioni & "Path:" & 

My.Application. Info. DirectoryPath & vbCrLf 

'Permette di visualizzare il nome del prodotto 

'associato all'applicazione. 

Informazioni = Informazioni & "Prodotto:" & 

My.Application. Info. ProductName & vbCrLf 

'Permette di visualizzare le informazioni relative 
'all'analisi dello stack corrente. 
Informazioni = Informazioni & "Stack:" & 

My.Application. Info. StackTrace & vbCrLf 

'Permette di visualizzare il titolo associato 

'all'applicazione. 

Informazioni = Informazioni & "Titolo:" & 

My.Application. Info. Title & vbCrLf 

'Permette di visualizzare le 

' informazioni sul marchio 

'associate all'applicazione. 

Informazioni = Informazioni & "Marchio:" & 

My.Application. Info. Trademark & vbCrLf 



'Permette di visualizzare la quantità di memoria 
' fisica associata al contesto del processo. 

Informazioni = Informazioni & "Memoria:" & 

My.Application. Info. WorkingSet & vbCrLf 

TextBoxl.Text = Informazioni 

L'oggetto CommandLineArgs, permette di 
ottenere una ReadOnlyCollection di stringhe 
che racchiude gli argomenti della riga di 
comando dell'applicazione corrente. 
Il codice seguente mostra in un TextBox, gli 
eventuali argomenti della riga di comando 
separati da punto e virgola (;) 

Dim s As String = "" 

Dim Informazioni As String = "" 

For Each s In 

My.Application. CommandLineArgs 
Informazioni = Informazioni & s & ";" 

Next 

TextBoxl.Text = Informazioni 

L'oggetto Culture permette di ottenere la lin- 
gua (cultura) utilizzata dal thread corrente, il 
che influenza aspetti come l'elaborazione e la 
formattazione delle stringhe. 
Per cambiare la lingua, possiamo utilizzare il 
metodo My.Application. ChangeCulture 



GESTIAMO LA LINGUA 

In questo esempio vediamo, in che modo, la 
lingua influenzi la rappresentazione in forma 
di stringa delle date. Definiamo la variabile 
che dovrà contenere la lingua corrente utiliz- 
zata nel sistema, e la inizializziamo 

Dim LinguaCorrente As String = 

My.Application. Cu Itu re. Na me 

Visualizziamo un messaggio che indica la lin- 
gua corrente (nel nostro caso l'italiano) 

MessageBox.Show ("La lingua utilizzata nel 

tuo sistema è: " & LinguaCorrente) 

Definiamo la variabile che dovrà contenere la 
data di test, e la inizializziamo al 26 Marzo 
2006 Ore 15:30 e 50 secondi. 

Dim DataDiProva As New Date(2006, 6, 26, 15, 

30, 50) 




GESTIRE 

LE IMMAGINI 

Le risorse immagine si 
possono assegnare alla 
proprietà Image di un 
controllo PictureBox in 
fase di progettazione 
senza scrivere una riga 
di codice. E' sufficiente 
passare alla finestra 
delle proprietà, cliccare 
il pulsante con i tre 
puntini e selezionare la 
risorsa tra quelle che si 
è definito nella pagina 
Risorse del designer. 



'Permette di visualizzare il numero 

'di versione dell'applicazione. 

Informazioni = Informazioni & "Versione:" & 

My.Application. Info. Version.ToString & vbCrLf 



Visualizziamo un messaggio che mostra la 
data di test con le impostazioni correnti 
(abbiamo impostato come lingua di default 
l'italiano) 



http://www.ioprogrammo.it 



Settembre 2006/ 83 ► 



SISTEMA T I Meno righe di codice con "My' 




MessageBox.Show (" 

Data del 26 Marzo 2006 
rappresentata nella lingua italiana:" & 
DataDiProva) 



Dim frml as New forml() 



Wi n dowsÀ p p licatio n 1 




SI 


Data del 26 Marzo 2006 rap 


presentata nelle 


lingua italiana: 26/06/2006 15.30.50 


OK 


3 







Frml. Show 

Con buona pace dei puristi della programma- 
zione ad oggetti, che con l'avvento della ver- 
sione 2.0 del Framework, si trovano a storcere 
il naso perché è possibile scrivere la seguente 
riga di codice equivalente al vecchio VB6 

My.Forms. formi. Show 



MAMESPACE 
ADATTABILI 

Una caratteristica del 

namespace My è che 

non tutti i suoi oggetti 

vengono creati per 

tutti i tipi di progetti. 

Ad esempio, l'oggetto 

My.Form è disponibile 

solo nelle applicazioni 

Windows Forms. Il 

namespace My espone 

alcuni oggetti che 

vengono creati 

dinamicamente ogni 

volta che si 

aggiungono 

caratteristiche al 

progetto corrente. 



Verrà visualizzato: 26/06/2006 15.30.50 
Cambiamo la lingua in Inglese 

My. Application. ChangeCul tu re("en-US") 

Visualizziamo un messaggio che mostra la 
data di test con le impostazioni in inglese 

MessageBox.Show ( 
"Data del 26 Marzo 2006 

rappresentata nella lingua inglese: " & 
DataDiProva) 




Verrà visualizzato: 6/26/2006 3:30:50 PM 
Ripristiniamo la lingua iniziale 

My.Application.ChangeCulture(LinguaCorrente) 



L'OGGETTO MY.FORMS 

L'oggetto My.Forms è subito disponibile, e 
definisce un metodo factory per ciascuna 
classe form definita nel progetto corrente. Le 
sue proprietà permettono di referenziare l'i- 
stanza di default di ciascuna Windows Form 
dichiarata nel progetto corrente, senza dover 
creare esplicitamente un oggetto della classe 
form. L'oggetto My.Forms da accesso ad una 
collezione che contiene i form dell'applica- 
zione e permette di accedere ai form come si 
faceva inVB6. 

Per i nostalgici, ricordiamo come in VB6, per 
mostrare uno dei form del progetto si doveva 
scrivere: 

formi. Show 

Con l'avvento del .NET Framework 1.0/1.1 
non è stato più possibile usare la stessa sin- 
tassi ma si doveva scrivere: 



Possiamo notare, come il nome della pro- 
prietà sia uguale a quello del form a cui si 
accede, ed il tipo di proprietà equivale a quel- 
lo del tipo di form. 

Ciascuna proprietà dell'oggetto My.Forms 
fornisce accesso a un'istanza di un form nel 
progetto corrente. Per rimuovere un form, si 
deve assegnare il valore Nothing alla relativa 
proprietà. Se alla proprietà si assegna un valo- 
re diverso da Nothing, il metodo per l'impo- 
stazione genera un'eccezione Argument 
Exception. 



L'OGGETTO 
MY.RESOURCES 

My.Resources contiene un oggetto per ciascu- 
na risorsa definita nel progetto corrente. Se, 
ad esempio, aggiungiamo al progetto una bit- 
map denominata EdMaster, sarà possibile 
accedervi mediante My.Resources. EdMaster. 
Le risorse offrono un utile strumento per rac- 
chiudere in un assembly informazioni che 
diversamente dovrebbero essere fornite come 
file separati. Ad esempio si possono racchiu- 
dere un file di testo ed un file sonoro come 
risorsa, in questo modo si può accedere al 
testo ed al suono contenuti in questi file, 
senza doverli distribuire separatamente. 



AGGIUNGERE RISORSE 

1 Selezioniamo il nostro progetto di prova, 
nella finestra: Esplora soluzioni e dal 
menu a tendina che si ottiene cliccando con il 
tasto destro del mouse, sulla nostra applica- 
zione, selezioniamo la voce: Proprietà 




»> 84 /Settembre 2006 



http://www.ioprogrammo.it 



Meno righe di codice con "My' 



T SISTEMA 



2 A questo punto, viene visualizzata la fine- 
stra delle proprietà con la scheda di 
default Applicazione. Per Cambiare scheda 
clicchiamo sulla scheda Risorse 



j;. •) 4 vi a » ■*•» * -i t> m li> 



"**% 



cativo valido di VB. Questo vincolo assicura 
che la risorsa possa essere esposta come pro- 
prietà dell'oggetto My.Resources. Le proprietà 
dell'oggetto My.Resources permettono di 
accedere in sola lettura alle risorse dell'appli- 
cazione. 

Se, ad esempio vogliamo accedere alla risorsa 
di tipo stringa (RisorsaStringa) definita in pre- 
cedenza, e visualizzarne il valore, possiamo 
scrivere: 

Dim EsempioRisorsa As String = 

My.Resources. RisorsaStringa 
MessageBox.Show( EsempioRisorsa) 




3 Aggiungere una risorsa di tipo stringa è 
molto semplice, è sufficiente inserire un 
nome di risorsa, il valore della stringa, ed un 
commento opzionale. 



4 Per inserire altri tipi di risorse, è sufficien- 
te trascinare un file esistente da Windows 
Explorer nella scheda Risorse. E', inoltre, pos- 
sibile creare una risorsa per mezzo degli edi- 
tor disponibili in Visual Studio. Se ad esempio 
vogliamo creare un'immagine come risorsa, 
dobbiamo cliccare sul pulsante Aggiungi 
Risorsa. Verrà mostrato un menù a discesa da 
cui possiamo selezionare la voce Nuova 
immagine ed il tipo di immagine da creare. 



, 


b*i Stringhe - 


_J Aggiungi risorsa - Rimuovi riso 
Aggiungi file esistente. , . 


se 












Nome 


Aggiungi nuova stringa 






Nuova immagine ¥ 


Immagine PNG... 




Aggiungi nuova icona 
Aggiungi nuovo file di testo 


ImmagiNBMP... 


Immagine GIF.,. 
Immagine JPEG... 
Immagine TIFF.,. 







Ogni volta che si aggiunge una nuova risorsa, 
nella scheda Risorse, queste vengono memo- 
rizzate nella cartella Resources della cartella 
del progetto (escluse le risorse stringa) e 
VB.NET popola l'oggetto My.Resources con il 
tipo corrispondente. Si possono aggiungere 
stringhe, immagini, icone, file .wav, ed ogni 
altro tipo di file. 

Ad ogni risorsa deve essere assegnato un 
nome, e questo nome deve essere un identifi- 



Possiamo notare come l'intellisense, dopo il 
punto, ci mostra i nomi di tutte le risorse 
disponibili 




Comuni 



Friend ReadOnly Property RisorsaStringaQ As String 
Cerca una stringa localizzata simile a Provami, 



Riassumendo, per ogni risorsa devono essere 
indicati: un nome, una categoria ed un valore. 
Il nome equivale al nome della proprietà, i 
dati della risorsa equivalgono al valore della 
proprietà, La categoria equivale al tipo della 
proprietà: 



L'OGGETTO 
MY.SETTINGS 

My.Settings mette a disposizione una pro- 
prietà per ciascuna impostazione di configu- 
razione determinata nelle impostazioni cor- 
renti; a livello di applicazione o per utente. 
Una risorsa a livello di applicazione può esse- 
re condivisa da tutti gli utenti, una risorsa a 
livello di utente può essere modificata dall'u- 
tente corrente. 

VB .NET memorizza le impostazioni in un file 
di configurazione XML, il cui nome corrispon- 
de al nome del file eseguibile seguito dall'e- 
stensione .config. Nel nostro caso: 
WindowsApplication l.exe. config In Visual 
Studio 2005 questi file di configurazione sono 
diventati più elastici e permettono di memo- 
rizzare impostazioni a livello di utente o di 
applicazione. Permettono, inoltre, di salvare 
le impostazioni quando l'applicazione termi- 
na. Le proprietà dell'oggetto My.Settings con- 
sentono di accedere alle impostazioni dell'ap- 
plicazione. Ad ogni impostazione sono asso- 
ciati: Nome, Tipo, Ambito, Valore: 



PERCORSI 
SEMPLIFICATI 

Il namespace My 
contiene un insieme di 
oggetti che forniscono 
percorsi semplificati a 
molte aree del .NET 
Framework, riducendo 
il numero di righe di 
codice che è necessario 
scrivere in maniera 
efficiente ed affidabile. 



http://www.ioprogrammo.it 



Settembre 2006/ 85 ► 



SISTEMA T I Meno righe di codice con "My' 




Nome, permette di determinare il nome 
della proprietà. 

Tipo, permette di determinare il tipo della 
proprietà. 

Ambito, indica se la proprietà è in sola let- 
tura. Se il valore è Applicazione, la pro- 
prietà è in sola lettura; se il valore è Utente, 
la proprietà è in lettura/scrittura. 
Valore, rappresenta il valore predefinito 
della proprietà. 



3 Clicchiamo sull'elenco a discesa nella 
colonna Tipo e selezioniamo la voce 
(stringa di connessione) 



m iiiiuuu.djiuiu utìii d|_i|_nii_d jiui ih lui itm il ui iu ui iindinuii^drtì e ruLupidrdry n iiiiuutLdJiuiii uuuu pi 

informazioni per l'applicazione. Ad esempiOj le preferenze di un utente relative ai colori possono t 
quindi recuperate alla successiva esecuzione dell'applicazione, 
■ ■ione... 



Nome 
ConnessioneDB 



Tipo 
String 



Ambito 
v Utente 



System. Guid 
5y sterri. Time5pan 
Ulnteger 
ULong 
LIShort 
URL idei servizio Web) 




USARE 
L'IIUTELLISENSE 

Gli oggetti del 

namespace My sono 

accessibili in modalità 

a tipizzazione forte, 

con l'aiuto di 

IntelliSense 

eliminando gli errori a 

runtime provocati da 

errori di digitazione. 



AGGIUNGERE UNA 
STRINGA DI 
CONNESSIONE A 
DATABASE 

1 Sempre dal nostro progetto di prova, nella 
finestra: Esplora soluzioni, selezioniamo la 
voce: Proprietà dal menu a tendina. 
Visualizziamo la scheda Impostazioni 



M 



t«««Mc4n«w;(«i 



(Scriviamo il nome identificativo dell'im- 
rpostazione, nella colonna Nome 



WindowsApplicationl* Formi. vb* Formi ,vb |Pkì guttazione]* Pagina iniziale 



Applicazione 

Compila 

Debug 

Riferimenti 

Risorse 

Impostazioni 

Firma 

Protezione 

Pubblica 



' 



Sincronizza Jj Visualizza codice 



Le Impostai none consentono di memorizzare e recuperare le imp 

informazioni per l'applicazione. Ad esempio, le preferenze di un utente relative a 
quindi recuperate alla successiva esecuzione dell'applicazione, Ulte -: 
dell'applicazione,.. 



Nome Tipo 

ConnessioneDE 1 5tring 



Ambito 
Utente 



■ 



4 



L'ambito di validità diventa automatica- 
mente a livello di applicazione 





Le impostazioni dell'applicazione coniente 
i ■ ■ ■ - 


le preferenze di 
ne dell'applicazion 


'■:■.■ i-i^V: ':. : !Y1 -<-K ■:,. 


oni delle proprie 


a e altre 


















| Nome Tipo 


Ambito 


Valore 






► 


ConnessioneDB 


■■ ' ■ :■ 1 


v Bff 


ai 






* 




■ '" 





5 Infine clicchiamo il pulsante con i tre pun- 
tini (...) nella colonna valore, apparirà la 
finestra di dialogo: Scegli origine dati, da cui 
si può scegliere anche una fonte dati ODBC 



Scegli origine dati 



Origine dati: 



Database Oracle 

File di database Microsoft Access 

File di database Microsoft SQL Server 

Microsoft SQL Server 

Microsoft SQL Ss»-ve? Mobile Editicm 

<altro> 



Descrizione 

Utilizzare questa selezione per 
specificare il nome di un'origine dati di 
sistema o di un utente ODBC per 
connettersi a un driver ODBC tramite 
il provider di dati .NET Framework per 
ODBC. 



Provider di dati: 



| Provider di dati ,NET Framework per ; 
Usa sempre questa selezione 



USO DEGLI OPERATORI IS E ISIMOT 



My.Settings espone inoltre i due Metodi 

• Reload, che permette di ricaricare le impo- 
stazioni dell'utente dagli ultimi valori sal- 
vati. 

• Save, che permette di salvare le imposta- 
zioni correnti dell'utente. 



Generalmente, l'operatore Is o 
IsNot deve leggere il valore della 
proprietà per eseguire il 
confronto. Tuttavia, se il valore 
della proprietà è Nothing, la 
proprietà crea una nuova istanza 
del form e quindi la restituisce. Il 



compilatore di Visual Basic 
considera le proprietà 
dell'oggetto My.Forms in modo 
speciale e consente all'operatore 
Is o IsNot di controllare lo stato 
della proprietà senza 
modificarne il valore. 



CONCLUSIONI 

Il namespace My semplifica moltissimo la vita 
al programmatore. Il suo utilizzo e semplice e 
immediato e le potenzialità enormi. Fatene 
buon uso. 

Luigi Buono 



► 86 /Settembre 2006 



http://www.ioprogrammo.it 



NETWORKING T ■ Usare il protocollo SNMP 



SNMP: SISTEMA 
SOnO CONTROLLO 

JAVA DISPONE DI ALCUNE CLASSI CHE CI CONSENTONO DI INTERFACCIARE LE NOSTRE 
APPLICAZIONI CON SNMP. UTILIZZANDO QUESTO PROTOCOLLO È POSSIBILE TENERE 
TRACCIA DELL'ATTIVITÀ DI TUTTE LE RISORSE DEL COMPUTER. VEDIAMO COME... 




LI CD J WEB 

SMRzip 



ftF""""""""" 1 """ 1 " 




n.i,i.wmiw.ima 

5] Basidi 

programmazione Java 



i 



JDK 1.4.1 o superiore 



l^g^g=3g=gj 



Durante l'estate capita più spesso di 
divertirsi con i giochi enigmistici 
come, ad esempio, quello di trovare le 
differenze o le uguaglianze tra due foto. Nella 
figura 1 ci sono 2 valori uguali tra quelli pre- 
senti nel Task Manager e tra i risultati del pro- 
gramma. Come gioco non è molto difficile, 
come risultato invece è decisamente più inte- 
ressante: il programma ha trovato che ci sono 
56 processi in esecuzione. Volendo, in modo 
analogo, si possono determinare i valori della 
memoria o la descrizione del computer, l'ulti- 
ma volta che è stato riawiato o la velocità 
della scheda di rete, o maggiori dettagli sui 
processi attivi con i loro identificativi e le 
porte sulle quali girano. E molto, molto altro! 
Questi parametri, inoltre, sono legati al fun- 
zionamento del computer e possono aprire 
molteplici scenari. 

Basti pensare agli allarmi da generare se un 
certo processo non è più attivo, o se i livelli di 
memoria libera scendono sotto una determi- 
nata soglia. Infatti, non di rado, capita di 
guardare nelle sale server, persone che, appe- 
na vedono un valore anomalo, riawiano un 
determinato servizio o un programma. 
Se questi valori del computer diventassero 
disponibili a livello di codice, si potrebbero 
anche intraprendere correzioni specifiche, 
come lanciare automaticamente un processo 
batch che liberi memoria o rilanci la procedu- 
ra che sta assorbendo troppe risorse, senza 
che ci sia materialmente qualcuno a farlo. 
L'obiettivo di questo articolo è di costruire 
una applicazione, semplice da realizzare, che 
consenta di ricavare tutti quei parametri di 
sistema che permettono di tenere sotto con- 
trollo il computer, impiegando delle Api 
molto intuitive da usare, dando a tutti il con- 
trollo completo sui computer. 
Tornando alla figura 1, si può notare come ci siano 
una serie di coppie di valori. A sinistra ci sono degli 
identificativi e a destra i corrispettivi valori. Il primo 
passo da compiere è capire il significato di questi 







, CktttUSH Poh i.Hril 







1 Md 


XWl Minfallim * 4nv<J 






13518 

593 
56 


Tofà. 

Dispg So£ 
,- J «mi» 



Fig. 1: Esempio dell'applicazione. 

identificativi e il protocollo che permette di interro- 
garli: in questo modo, infatti, si può comprendere 
dove possono essere lanciati i vari elementi dell'ap- 
plicazione e perché sia così facile reperire i dati che 
interessano. 



SNMP, SIMPLE NETWORK 
MANAGEMENT PROTOCOL 

È il protocollo (standard di fatto) di comunicazione 
per la gestione e il controllo della rete. I suoi punti di 
forza sono la semplicità e la facilità di uso. E anche 
l'estendibilità, consentendo l'introduzione di fun- 
zionalità e parametri aggiuntivi specifici per i diver- 
si dispositivi e periferiche. Gli elementi che costitui- 
scono l'architettura, come si può vedere bene in 
figura 2, sono di 2 tipi: un manager e gli agenti. Gli 
agenti hanno il compito di memorizzare e gestire i 
dati che interessano e possono inviare messaggi al 
manager. Il manager, a sua volta, ha diverse intera- 
zioni con gli agenti che può interrogare per verifi- 
carne i valori, ottenerne le risposte, può impostare i 
parametri e ricevere i messaggi. Già da questa prima 
descrizione si può tracciare il parallelo con quanto 
riportato in figura 1. Un manager ha interrogato un 
agente che gli ha fornito le risposte circa i parametri 
chiesti. E sono proprio i parametri che risultano 
ancora non ben definiti: cosa sono quelle sequenze 
come 1.3. 6.1.2. 1.25.1? Queste serie di numeri sono le 
unità elementari per gestire le informazioni e cioè i 
MIB, managment information base. In poche paro- 



► 88 /Settembre 2006 



http://www.ioprogrammo.it 



Usare il protocollo SNMP ■ T NETWORKING 



le, a ogni sequenza numerica corrisponde un valore. 
Nell'esempio di prima, 1.3.6.1.2.1.25.1.6.0 è l'identi- 
ficativo riconosciuto che corrisponde al numero di 
processi attivi sulla macchina. Per poter essere inter- 
rogati da tutti, i MIB devono essere univoci e univer- 
sali, permettendo di richiedere informazioni su 
macchine diverse, con hardware e sistemi operativi 
differenti, e ottenere sempre risposte congruenti. 
Considerando che SNMP è molto utilizzato, ci sono 
già le librerie che lo implementano. In questo caso, 
si utilizzerà snmp4j, un insieme di classi Java che 
permettono di sviluppare le applicazioni in modo 
estremamente semplice. SNMP è un protocollo di 



Manager 
SNMP 



SNMP/ 



7^ 



\SNMP 



Agente 

SNMP 



MIB 
Computer 1 



Agente 

SNMP 



Agente 

SNMP 



Computer 2 



Computer 3 



Fig. 2: Architettura SNMP 

comunicazione tra manager e agenti che si scam- 
biano messaggi. E sono proprio i messaggi che per- 
mettono di mandare informazioni sui parametri e 
sullo stato del computer. 



Le istruzioni sopra servono per dire che si voglio- 
no informazioni relative alla macchina locale, 
127.0.0.1, e che si chiederanno sulla porta di 
default del protocollo UDP la 161. Inoltre si 
imposta la comunità a public, per poter accede- 
re ai parametri disponibili a tutti. 

// preparare il PDU per l'invio messaggio 
PDU pdu = new PDU(); 
pdu.setType(PDU.GET); 
pdu.add(new VariableBinding(new 

OID("1.3.6.1.2.1.25.1.6.0"))); 

Con queste direttive, si dichiara il comando da 
usare, GET, e il parametro per il quale si desidera 
conoscere il valore, 1.3.6.1.2.1.25.1.6.0. Le classi di 
snmp4j usano i nomi del protocollo. In particolare, 
OID, Object Identifier, è l'identificativo dell'oggetto 
caratterizzato dalla sequenza di numeri che attra- 
versano l'albero e PDU, Protocol Data Unit, l'unita 
dei dati come ad esempio GET e GETNEXT. 

Snmp snmp = new Snmp(new 

DefaultUdpTransportMappingO); 
snmp.listen(); 
// invio del PDU 
ResponseEvent responseEvent = snmp.send 

(pdu, target); 
if (responseEvent != nuli) { 
// gestione della risposta 
PDU pduResponse = responseEvent. getResponseQ; 



System. out.println("res: " + 




pduResponse.toStringO); 



NUMERO DI PROCESSI 

L'esempio iniziale determinava quanti processi 
sono attivi sulla macchina. Per ottenere questo risul- 
tato, si può usare il comando GET del protocollo 
SNMP Questo comando consente di ricavare il valo- 
re di un parametro specifico. Naturalmente il grosso 
del lavoro è svolto dalle api snmp4j che devono esse- 
re solo invocate correttamente. Quello che vera- 
mente serve sono 3 elementi: 1) la configurazione 
dei parametri relativi alla macchina, alla quale chie- 
dere le informazioni, 2) la definizione del parametro 
da chiedere e 3) l'esecuzione dello scambio dei mes- 
saggi. Il codice mostra la semplicità di questi passi. 

// Classe IoPGET 

// configurazione Snmp 

UdpAddress targetAddress = new 

UdpAddress("127. 0.0. 1/161"); 
CommunityTarget target = new CommunityTarget(); 
target. setCommunity (new OctetString("public")); 
target. setAddress(targetAddress); 



A questo punto basta solo inoltrare la chiamata e 
aspettare la risposta. Il comando GETNEXT è simile 
e serve per prendere i valori successivi dell' OID. 

pdu. setType(PDU. GETNEXT); 
pdu.add(new VariableBinding(new 

OID("1.3.6.1.2.1.1.5.0"))); 

Il commando GET restituisce il nome del computer, 
GETNEXT, invece, prende l'identificativo o gli iden- 
tificativi successivi, ad esempio il 1.3.6.1.2.1.1.6.0 
che corrisponde alla posizione della macchina 



INVIARE I PARAMETRI 



Un altro modo per usare le api 
snmp4j è lanciando la classe 
org.snmp4j.tools. console. Snmp 
Request con vari parametri 
come specificato nella classe 
stessa. Un esempio di 
parametri è : -p TRAP -v 3 -u 



aSecurityName 127.0.0.1/162 

"1.3. 6.1.2. 1.1.3.0={t}0" 

" 1.3.6. 1.6.3. 1.1. 4.1. 0={o}1. 3.6.1. 

6.3.1.1.5.1" 

" 1.3.6.1. 2.1. 1.1.0={s}System 

XYZ, Version N.M" 



http://www.ioprogrammo.it 



Settembre 2006/ 89 ► 



NETWORKING T ■ Usare il protocollo SNMP 




all'interno della rete. A questo punto ci si può diver- 
tire a prelevare tutte le informazioni che servono. Ad 
esempio il valore 1.3.6.1.2.1.1.1.0 serve per avere 
informazioni hardware e sistema operativo del com- 
puter, 1.3.6.1.2.1.1.3.0 indica da quanto tempo il 
sistema è attivo, 1.3.6.1.2.1.1.5.0 è il nome del com- 
puter, e così via. Ora serve solo un po' di ricerca per 
trovare gli identificativi che interessano. I comandi 
considerati prima servono per prendere i valori del 





Root 








I I 


l 






ccitt 





iso 

1 

I 

org 

3 

I 
dod 

6 

l 




joint-iso-ccitt 
2 
















Internet 
1 








I 








I I 




directory 
1 


mgmt 
2 


experiment; 
3 


il private security snmpV2 
4 5 6 




I 




I 






mib-2 
1 




enterprise 
1 


s 























Fig. 3: Gerarchia MIB. 



manager. In questo caso si dovranno realizzare sia il 
manager, che resta in ascolto di possibili problemi 
dell'agente, sia l'agente che invia la comunicazione. 
Generalmente la parte più importante spetta al 
manager che, in base all'allarme generato, compie le 
modifiche necessarie. Anche in questo caso servono 
poche righe di codice per catturare quella che nel 
protocollo viene definita TRAE 

// Classe IoPTrapListener 
// gestione della trap 

CommandResponder trapPrinter = new 

CommandResponder() { 
public synchronized void 

processPdu(CommandResponderEvent e) { 
PDU command = e.getPDU(); 
if (command != nuli) { 

System. out.println(command.toString()); 
// gestione specifica... 



}; 

snmp.addCommandResponder(trapPrinter); 

Da notare anche la gestione di thread concorrenti 
grazie all'uso del syncronized. In questo modo il 
manager è in ascolto. Dall'altro lato, invece, un 
agente invia la TRAE 



computer. Se invece si volesse impostare un valore, 
allora si può usare il comando SET. E con questo 
comando, termina l'insieme delle operazioni più 
dirette da compiere. In realtà si possono aprire sce- 
nari più interessanti. 



LA FINE DEI PROBLEMI 

Una situazione tipica per un server è che vi giri 
un'applicazione. E se l'applicazione, per qualche 
motivo, non dovesse più funzionare? E se assorbisse 
troppe risorse? Ritornando all'architettura di SNMP 
ci sono 2 attori, il manager e gli agenti. 
Implicitamente, nell'esempio di prima, si è assunto 
che il programma funzionasse da manager e inter- 
rogasse un agente chiedendogli i parametri. In realtà 
ci si può mettere nei panni dell'agente che gira sul 
server il quale, accorgendosi, ad esempio, che un 
processo non è più attivo, invia una segnalazione al 



E SMMP4J DA CONSOLE 



Un altro esempio dell'utilizzo 
delle api snmp4j è realizzato 
dalla console snmp4j-agent 
presente anch'essa nel file 



allegato. Può funzionare come 
applicazione a sé e, grazie al 
codice sorgente, può dare intere 
righe di codice funzionante. 



V- 



PDUvl pdu = new PDUvl(); 

pdu.setType(PDU.VlTRAP); 

pdu.setGenericTrap(PDUvl.COLDSTART); 



Per mandare le TRAP si possono usare varie classi, a 
seconda della versione del protocollo. La classe base 
è PDU che imposta il proprio tipo usando 
.setType(PDU.TRAP). Invece, per la versione 1 di 
SNMP si può usare la classe PDUvl che è derivata da 
PDU. L'ulteriore parametro, COLDSTART, tiene 
conto delle possibili modifiche che possono influire 
sulla configurazione dell'agente. 



SICUREZZA 

Dagli esempi e dall'architettura si nota che SNMP 
può funzionare sia in locale, per controllare la pro- 
pria macchina e prendere i parametri, sia, soprattut- 
to, in contesti distribuiti. Uno scenario tipico è un 
manager installato su una macchina e vari agent sui 
computer da tenere sotto controllo che si scambia- 
no messaggi. Inutile dire che a molti viene l'acquoli- 
na in bocca solo a pensare come fare a inserirsi nello 
scambio di messaggi, a contraffarli, a provare a man- 
dare informazioni sbagliate. Ed effettivamente, se a 
fronte di un messaggio di TRAP lanciato da un agent, 
il manager decidesse di riavviare un servizio, a un 
hacker basterebbe lanciare TRAP una dopo l'altra 



»> 90 /Settembre 2006 



http://www.ioprogrammo.it 



Usare il protocollo SNMP ■ T NETWORKING 



per mandare giù tutto il sistema. Al di là dell'esem- 
pio, e se ne potrebbero fare molti altri, il problema 
della sicurezza è decisivo anche in questo caso. 
SNMP utilizza due elementi per validare una mac- 
china che vuole scambiare messaggi: il nome della 
comunità e l'indirizzo IR In particolare, quello che è 
possibile gestire via codice è la comunità e per farlo 
servono due righe di codice. 

CommunityTarget target = new CommunityTarget(); 
target. setCommunity(new OctetString("public")); 

Già in questo modo si ha una certa garanzia di con- 
cedere solo i privilegi necessari. Ricordando, infatti, 
i parametri che si possono ottenere da una macchi- 
na, alcuni di essi possono essere letti e modificati, 
altri è necessario solo leggerli senza dare la possibi- 
lità di modifica. Ad esempio si può voler modificare 
i parametri di timeout, mentre non avrebbe senso 
cambiare l'identificativo, univoco, delle interfacce 
di rete. Un ulteriore livello di sicurezza può essere 
impostato via codice usando le api snmp4j e la crit- 
tografia. Questa volta le righe di codice sono un po' 
di più perché gli elementi in causa sono più nume- 
rosi: il protocollo, l'utente, il destinatario e il sistema 
di crittografia. Il codice è comunque abbastanza 
auto esplicativo. 

// Classe IoPAuth 

MPv3 mpv3 = 

(MPv3) 
snmp.getMessageProcessingModel(MessageProcessing 

Model. MPv3); 
USM usm = new 

USM(SecurityProtocols.getInstance(), 
new OctetString(mpv3.createLocalEngineID()), 0); 
SecurityModels.getInstance().addSecurityModel(usm 

transport.listen(); 



// aggiunta dello user all' USM 



snmp.getUSM().addUser(new 



OctetString("MD5DES"), 



new UsmUser(new OctetString("MD5DES"), 



AuthMD5.ID, 



new OctetString("MD5DESUserAuthPassword"), 



PrivDES.ID, 



new OctetString("MD5DESUserPrivPassword"))); 



// creazione del targhet 



UserTarget target = new UserTargetQ; 



target. setVersion(SnmpConstants.version3); 
target. setSecurityLevel(SecurityLevel.AUTH_PRIV); 
target. setSecurityName(new 

OctetString("MD5DES")); 



si usa e, in questo caso, è la versione 3 di SNMR Vi è 
poi la classe relativa all'utente, USM, User Based 
Security Model, che ne gestisce anche le credenziali. 
Le ultime righe servono per impostare i parametri 
dei messaggi e della sicurezza anche sulla macchina 
targhet, quella alla quale mandare i messaggi. I pro- 
tocolli di crittografia che si possono usare dalle api 
sono MD5, DES, come nell'esempio, e anche AES e 
SHA. In poche parole sono rappresentati tutti modi 
usati attualmente per rendere sicuro lo scambio di 
informazioni in rete. Un'altra istruzione utile è rela- 
tiva al livello di sicurezza. La classe SecurityLevel 
definisce i livelli di sicurezza che possono essere 
usati. Entrando nel codice ci sono dichiarate 3 
costanti che sprigionano scenari assai diversi tra di 
loro. 




// Classe SecurityLevel 


public 


static final 


int NOAUTH_NOPRIV = 1; 


public 


static final 


int AUTH_ 


_NOPRIV = 2; 


public 


static final 


int AUTH_ 


_PRIV = 3; 



Anche i nomi sono di facile interpretazione. Nel 
primo caso, chiunque può creare e leggere messag- 
gi. L'altro caso estremo è l'ultimo dove solo chi ha la 
chiave per autenticarsi può creare messaggi e solo 
chi ha le chiavi per criptare e decriptare può leggere 
il contenuto dei messaggi. Il secondo caso è quello 
intermedio dove per creare i messaggi serve la chia- 
ve e tutti possono leggerli. In questo ultimo caso c'è 




Per sapere cosa è esattamente un 
mib e vedere tutti parametri che 
si possono usare, basta ricercare, 
sulla macchina, i file con 



possono leggere le definizioni dei 
mib e il codice numerico 
associato ai parametri. 





Root 








I I 


l 






ccitt 





iso 

1 

I 

org 

3 

I 
dod 

6 

l 




joint-iso-ccitt 
2 
















Internet 
1 








I 








I I 




directory 
1 


mgmt 
2 


experiment; 
3 


il private ; 
4 


security 
5 


snmpV2 
6 




I 




I 






mib-2 
1 




enterprise 
1 


s 























Lo scambio dei messaggi dipende dal protocollo che Fig. 4: Flusso dei messaggi 



http://www.ioprogrammo.it 



Settembre 2006/ 91 »- 



NETWORKING T ■ Usare il protocollo SNMP 




una asimmetria con sicurezza solo su chi crea il 
messaggio che, in generale, è anche la parte più deli- 
cata. 



MESSAGGI 

Dopo aver visto che sono veramente pochi i tipi di 
messaggio che si possono inviare e aver considerato 
i problemi di sicurezza, si può passare a un altro dei 
problemi che coinvolge la rete: lo scambio dei mes- 
saggi. Lo scambio dei messaggi avviene in 2 modi: 
sincrono e asincrono; il primo caso è come l' invo- 
cazione di una pagina web con un browser che fa 
una richiesta a un server e resta in attesa finché il 
server gli restituisce la pagina desiderata oppure si 
verifica un timeout. Il secondo caso è come quello 
della posta elettronica: la posta viene inviata da un 
utente che non resta in attesa finché il destinatario 
non la legge. La differenza principale tra queste due 
modalità è nel fatto che un messaggio sia bloccante 
o meno e cioè se il mittente resta in attesa di rispo- 
sta o può scollegarsi appena inviato il messaggio. 
Considerando le velocità e la garanzia dei servizi, 
spesso non è possibile aspettare 2 minuti prima di 
ricevere un timeout e nel frattempo bloccare tutti gli 
altri messaggi. Ecco quindi che, se si vogliono sfrut- 
tare appieno le caratteristiche di snmp4j, si dovrà 
tenere conto anche di come inviare e ricevere i mes- 
saggi. Anche in questo caso le operazioni da com- 
piere sono poche e semplici e avranno poi impatti 
importanti ai fini delle prestazioni. Un esempio di 
messaggio sincrono che aspetta una risposta imme- 
diata è il seguente. 



if (response.getResponse() == nuli) { 



Il caso di messaggio sincrono si basa sull'uso della 
classe ResponseEvent nella quale viene scritto 
anche l'esito del messaggio. Anche il codice per 
mandare messaggi asincroni è facile. 



Snmp snmp = new 


Snmp(new 
DefaultUdpTransportMappingO); 




ResponseListener listener = new ResponseListener() 

{ 


public void onResponse(ResponseEvent event) { 


PDU response 


= event. getResponse(); 


PDU request = 


event. getRequest(); 


if (response = 


= nuli) { 


System, out. 


3rintln("Request "+request+" 

timed out"); 


} 


else { 


System. out. 


3rintln("Received response 

"+response+" on request " + 


request); 


} 


}; 


snmp.sendPDU(rec 


uest, target, nuli, listener); 





In questo caso è la classe ResponseListener che invia 
messaggi in modalità asincrona usando una classe 
interna e l'oggetto PDU per prendere i dati. Questa è 
la struttura di chi invia il messaggio. In modo specu- 
lare, chi riceve il messaggio deve porsi in ascolto. 



Snmp snmp = new Snmp(new 

DefaultUdpTransportMappingO); 



ResponseEvent response 



snmp.send(requestPDl), 

target); 



Gruppo 


Parametro 


Descrizione 


System 


1.3.6.1.2.1.1.1.0 


Descrizione testuale della macchina 


System 1.3.6.1.2.1.1.3.0 


Tempo dall'ultimo riawio 


System 1.3.6.1.2.1.1.6.0 


Posizione fisica 


Interfacce 1.3.6.1. 2.2. 1.2.iflndex 


Descrizione dell'interfaccia 


Interfacce 


1.3.6.1.2.1.2.2.1.4.iflndex 


Dimensioni massime pacchetto 


IP 


1.3.6.1.2.1.4.2.0 


Valore Ip 


IP 


1.3.6.1.2.1.4.3.0 


Numero pacchetti ricevuti 


TCP 


1.3.6.1.2.1.1.6.10.0 


Numero pacchetti ricevuti 


TCP 


1.3.6.1.2.1.6.12.0 


Numero segmenti ritrasmessi 


UDP 


1.3.6.1.2.1.7.5.1.1 


Indirizzo IP locale 


SNMP 


1.3.6.1.2.1.11.25.0 


Numero di GET 


SNMP 


1.3.6.1.2.1.11.30.0 


Permesso di generare trap 


Vari 


1.3.6.1.2.1.25.2.2.0 


Dimensione totale memoria 


Vari 


1.3.6.1.4.1.2.6.191.2.4.2.1.4.1 


Dimensione pagine di swap 


Vari 


1.3.6.1.2.1.25.2.3.1.5.8 


Memoria libera 


Vari 


1.3.6.1.4.1.17384.1.1.1 


Temperatura 





snmp.addCommandResponder(this); 
transport.listen(); 

public synchronized void 

processPdu(CommandResponderEvent e) { 
PDU command = e.getPDU(); 
if (command != nuli) { 



MIB 

Usare SNMP ha senso se ci sono dei parametri che 
interessano. E in realtà i parametri sono davvero 
molti e seguono una logica ben precisa. Come si può 
vedere dalle figure 3 e 5, i primi valori, 1.3.6.1, sono 
uguali per molti dei parametri principali. Sotto al 
nodo che caratterizza internet, i due valori più 
comuni sono 4, private, e 2, mgmt. Sotto mgmt ci 
sono i parametri del MIB2 e sono i più noti. Il grup- 
po 1, system, ha delle informazioni sul sistema come 



► 92 /Settembre 2006 



http://www.ioprogrammo.it 



Usare il protocollo SNMP ■ NETWORKING T 

















iso.org. internet, mgmt 
1.3.6.1.2. 








I 








mib-2 
1 












1 1 1 1 1 


I I 


system 
1 


interfaces 
2 


at 
3 


ip 
4 


icmp 
5 


tcp 
6 


udp 
7 


egp 
8 


transmission 
10 


snmp 
11 


I I I I I I I I I I 



Fig. 5: Gerarchia MIB II 

la descrizione del sistema operativo, e il tempo tra- 
scorso dall'ultimo riawio. Il gruppo delle interfacce 
di rete da informazioni sulle schede, e poi ci sono i 
gruppi per IP ICMP TCP UDP SNMP e errori. Dare 
una descrizione completa di tutti sarebbe molto 
lungo. Alcuni di questi parametri sono riportati in 
tabella. 



STORIA 

Dalle situazioni analizzate in precedenza, emerge 
prepotentemente la possibilità di verificare i para- 
metri e, se sono errati, compiere modifiche corretti- 
ve. Può essere utile, quindi, salvare tutti i dati nel 
database. In questo modo si può sempre accedere ai 
valori che aveva un determinato parametro nel 
corso del tempo. Ovvero si può ricavare la storia di 
un determinato parametro. Per poter effettuare que- 
ste operazioni, si deve organizzare le informazioni 
che si possono recuperare per poterle poi inserire in 
un database. Si può scegliere un qualsiasi database, 
anche gratuito, e il codice resta quasi invariato. Nel 
caso specifico il database di riferimento è Oracle. I 
passi da seguire sono essenzialmente 3: 1) recupero 
del parametro di interesse, 2) formattazione adegua- 
ta del parametro da inserire nel database, 3) inseri- 
mento nel database. Questo flusso viene gestito da 
una classe principale che a sua volta chiama le due 
classi specifiche per il recupero del dato e per la 
memorizzazione. 

// Classe IoPStore 

//recupero dati 

IoPGET iopGET = new IoPGET(); 

String keyValue = iopGET.getKeyValue(); 

//formattazione dati 

String key; 

String value; 

String[] splitted = keyValue. split(" = "); 

key = splitted[0]; 

value = splitted[l]; 



//inserimento nel db 

OracleDAO oracleDAO = new OracleDAO(); 

oracleDAO.insertValue(key, value); 



Come si può esaminare dal codice, le operazioni 



sono semplici. La classe IoPGET è quella utilizzata 
negli esempi precedenti per recuperare i valori. Il 
dato che viene fornito è del tipo <chiave> = <valore> 
e quindi si rende necessaria un'operazione di split 
per dividere chiave e valore da passare poi alla clas- 
se OracleDAO che si occupa della memorizzazione. 

//Classe OracleDAO 
private Connection con; 
private Statement stmt; 



try { 



prepareConnection(); 



stmt = con.createStatement(); 



stmt.executeUpdate("INSERT INTO PARAM (IDKEY, 
VALUE, RETRIEVETIME) " + 
"VALUES ("' + key + "', '" + value + "', 

SYSDATE)"); 



stmt.closeO; 



con.close(); 



} catch (SQLException e) {...} 

Per inserire il record serve solo prendere una con- 
nessione, inizializzarla con i parametri specifici del 
database ed eseguire lo statement. 



CONFIGURAZIONI 

Il protocollo SNMP è implementato da molti softwa- 
re che possono da operare sia da manager sia da 
agenti. Nei dischi di installazione sono già presenti, 
sia nelle varie versioni Windows sia Linux. Questi 
prodotti funzionano sulle porte udp standard, 161 e 
162 e possono colloquiare con le classi che vengono 
realizzate a patto che queste usino le stesse porte. 
Viceversa, se si vogliono realizzare sia manager che 
agenti, si deve verificare che le porte usate siano 
libere. Comandi utili sono netstat e ps che visualiz- 
zano i processi attivi e le porte corrispondenti. In 
questo modo si può anche verificare se sono stati 
installati più programmi che usano il protocollo 
SNMP e quale di essi è effettivamente funzionante. 



CONCLUSIONI 

Il protocollo SNMP garantisce il controllo delle mac- 
chine e, con pochi e semplici comandi, permette 
tutta le gestione di intere reti. Le api snmp4j sono 
molto utili per chi voglia realizzare programmi per- 
sonalizzati per la gestione del sistema. Essendo poi 
scritte in Java, funzionano su tutti i sistemi operativi 
e non serve software aggiuntivo per far comunicare 
e amministrare una rete di macchine di qualsiasi 
tipo. 

Cristiano Bellucci 




http://www.ioprogrammo.it 



Settembre 2006/ 93 ► 



Gestire Windows a linea di comando ■ T SISTEMA 



ARRIVA LA SHELL 
DI WINDOWS 

GLI UTENTI UNIX SONO ABITUATI A LAVORARE A RIGA DI COMANDO. DOPO TANTI 

ANNI ANCHE MICROSOFT HA DECISO DI FORNIRE STRUMENTI AVANZATI 

DI AUTOMAZIONE PER LA GESTIONE DEL SISTEMA BASATI SU SHELL. VEDIAMO QUALI 



In questi ultimi mesi si sente spesso parlare di un 
nuovo componente, che sarà rilasciato con la 
nuova versione del sistema operativo Windows, 
denominato Monad. Non è passato molto tempo, 
però, da quando la stessa Microsoft ha modificato 
ed ufficializzato nome definitivo con cui intende 
indicare questo "nuovo" oggetto: Windows 
PowerShell. 

Malgrado il termine PowerShell possa far pensare 
"semplicemente" ad una delle tante nuove utility di 
casa Microsoft, l'ex- Monad (com 1 eravamo "abituati" 
a chiamarla) o MSH, come vedremo, è certamente 
qualcosa di più di una semplice shell. In questo arti- 
colo passeremo in rassegna alcuni degli aspetti che 
ruotano attorno ad essa, sottolineando sin d'ora che 
quanto mostreremo è, in realtà, solo una minima 
parte di quello che la PowerShell è in grado di fare. 



PREMESSA 

Iniziamo subito questo percorso dicendo (e ras- 
sicurando tutti) che la tecnologia oggetto di que- 
sto articolo sarà integrata nativamente nel nuovo 
sistema operativo Windows Vista, ma che verrà 
resa disponibile anche su Windows XP e 
Windows Server 2003 mediante l'applicazione di 
una patch. 

Al momento in cui scriviamo, è possibile comin- 
ciare a prendere visione del funzionamento di 
questa shell collegandosi al sito della Microsoft 
http://www.microsoft.com/downloads/details.aspx7Fa 
milyld = 2B0BBFCD-0797-4083-A817- 
5E6A054A85C9&displavlanq=en e scaricando quan- 
to necessario alla sua esecuzione. 
La Windows PowerShell necessita dell'installa- 
zione del .NET Framework 2.0 RTM, scaricabi- 
le dal medesimo link ed indispensabile per il 
suo funzionamento. Per i test sono stati utiliz- 
zati due PC separati, il primo con Windows XP 
Home Ed. ed il secondo con Windows 2003 R2. 
In entrambi i casi, è bene sottolinearlo, non 
sono stati riscontrati particolari problemi di 
compatibilità o altro. 



Per cominciare, a questo punto, partiamo subito 
da una piccola considerazione, dando per scon- 
tato che l'installazione della PowerShell e del 
.NET Framework sia terminata senza particolari 
problemi. Tutti quanti noi ricordiamo perfetta- 
mente il significato che avevano i file 
Autoexec.bat e Config.sys. Questi file erano utili 
per impostare determinati parametri all'avvio 
del computer o, comunque, in grado di preimpo- 
stare l'ambiente in base alle esigenze. 
La Windows PowerShell consente di configurare 
il proprio ambiente in maniera analoga, serven- 
dosi di appositi file con estensione PS1 (la nuova 
estensione con cui vengono contrassegnati gli 
script PowerShell) . 

Dalla documentazione a corredo del pacchetto, 
si evince che all'avvio della shell vengono carica- 
ti diversi profili, nell'ordine seguente: 

Documents and Settings\AII 

Users\Documents\PSConfiguration\profile.psl; 
Documents and Settings\AII 

Users\Documents\PSH\Microsoft. Power 

Shell_ profile. psl; 
$HOME\My Documents\PSConfiguration\ 
profile. psl; 



$HOME\My 



Documents\PSH\Microsoft.PowerShelLprofile.ps!. 

Ciascun file di profile serve a caricare impo- 
stazioni comuni e non a tutti gli utenti della 
shell. Onde evitare inutili perdite di tempo, si 
tenga presente che la dicitura $HOME equiva- 
le proprio alla variabile d'ambiente HOME 
preimpostata all'interno della PowerShell. Per 
vederne il contenuto è sufficiente lanciare il 
comando $HOME direttamente dalla linea di 
comando della shell. Un possibile valore, ad 
esempio, potrebbe essere C:\Document and 
Settings\Francesco . 

Al momento sembrerebbe che l'installazione 
della PowerShell contenuta all'interno del pac- 
chetto offerto dalla Microsoft non si preoccupi 
affatto di creare queste cartelle né tantomeno di 




n 




REQUISITI 



EESSESSa 

j Basi di 
programmazione 



OS Microsoft, 
Windows Powershell 




http://www.ioprogrammo.it 



Settembre 2006/ 97 ► 



SISTEMA T 



Gestire Windows a linea di comando 




provvedere a file standard a cui fare riferimento. 
Per motivi di spazio, ma anche e soprattutto per- 
ché l'argomento può essere approfondito solo 
dopo una minima conoscenza di base sul nuovo 
linguaggio di scripting, non ci soffermeremo su 
questo "particolare". In ogni caso, quando sare- 
mo pronti, tutto quello che occorrerà fare, sarà 
creare le cartelle nell'ordine visto precedente- 
mente ed, al loro interno, inserire i file di profilo 
necessari seguendo la nomenclatura vista prima. 
Nel caso sia la prima volta che avviamo la 
PowerShell, ci verrà mostrato un messaggio 
importante che ci avverte sull'impossibilità di 
avviare script. Questo avvertimento, noto come 
Execution Policy, è ovviamente inteso a proteg- 
gere il sistema dall'esecuzione di codice non 
sicuro. Per modificare in qualunque momento le 
eventuali restrizioni impostate, è sufficiente lan- 
ciare il comando Set-ExecutionPolicy seguito dal 
parametro (numerico o testuale) corretto che ne 
identifica l'eventuale comportamento, secondo 
le indicazioni seguenti: 

• UnRestricted (0): nessuna restrizione; 

• RemoteSigned (1): tutti gli script scaricati da 
web devono avere una firma digitale di un pro- 
prietario garantito; 

• Allsigned (2): tutti gli script devono avere una 
firma digitale per poter essere eseguiti; 

• Restricted (3): nessuno script può essere avviato. 

Per esempio, i due comandi seguenti sono asso- 
lutamente equivalenti: 

Set-ExecutionPolicy UnRestricted 
Set-ExecutionPolicy 



Q! Windows PowerShell 



ronc 

Get-Help 



^HORT DESCHIPTION 

Displays help about PowerShell cmdlet s and concepts 



LONG DESCHIPTION 



ÌVNTBX 

get-help «CmdletName> ! <TopicName» 
help << Cndlet Nane > ! <TopicName» 
<CmdletNane> -? 



"Get-help" and "-?" display help on one page . 
"Help" displays help on multiple pages. 

Exanples: 

get-help get-process : Displays h 

get-help about-signing : Displays h CJ . P <&»«»•■ ■...«* £ . J . a "-"'a ^"h^f<-. 

help where-object : Displays help about the where-object cndlet. 

help about_Foreach : Displays help about foreach loops in PowerShell. 

natch-string -? : Displays help about the natch-string cndlet. 

Vou can use wildcard characters in the help connands <not with -?>. 
If multiple help topics match, PowerShell displays a list of matching 
topics. If only one help topic matches, PowerShell displays the topic. 

Exanples: 

get-help * : Displays ali help topics. 

get-help get-» : Displays topics that begin with get-. 

help *object* : Displays topics with "object " in th" ' 



Fig. 1: Porzione dell'output prodotto dal cmdlet get-help 



Solo per curiosità, ecco la chiave del Registry 
sulla quale hanno impatto tali modifiche: 
/ /HKEY_LOCAL_MACHINE / SOFTWARE / Micros 
oft / PowerShell / 1 / Shelllds / Microsoft.PowerShell 
\ExecutionPolicy. 

Prima di passare al concetto base della 
PowerShell, le Cmdlet, terminiamo queste poche 
righe menzionando subito il comando che ci 
permetterà, in qualunque momento, di ricavare 
informazioni d'aiuto sulla shell: get-help. Se lo 
lanciamo, otterremo a video una lunga descrizio- 
ne che illustra i metodi con cui possiamo sfrut- 
tarlo. Inutile ribadire sin d'ora che, col passare 
del tempo, scopriremo molto presto di non 
poterne più fare a meno. 



CENNI SUI CMDLET 

Il concetto attorno al quale ruota l'utilizzo della 
nuova shell di casa Microsoft è certamente costi- 
tuito da questi oggetti. Pronunciato "command 
let", questo termine identifica genericamente 
uno dei tanti comandi che possiamo utilizzare 
all'interno dell'ambiente offerto dalla Power 
Shell. Ad onor del vero, va sottolineato che la 
maggior parte delle cmdlet sono molto di più di 
un semplice comando ed avremo modo di ren- 
dercene conto con l'esperienza. 
Innanzitutto, se lanciamo il comando get-com- 
mand otteniamo la lista di tutti i cmdlet disponi- 
bili con accanto una parziale descrizione. 
L'elenco è piuttosto lungo (se ne contano 129). 
Alcuni di essi sono intuitivamente semplici da 
utilizzare, per altri invece, occorre documentar- 
si prima di capire realmente a cosa servano e 
soprattutto come utilizzarli. 
Un cmdlet può essere lanciato allo stesso modo 
in cui eravamo abituati ad avviare qualunque 
comando in ambiente DOS. 
Ecco a titolo d'esempio qualche cmdlet che può 
risultarci utile: 

• get-service: produce una lista di tutti i servizi 
avviati e non sul sistema; 

• get-process: produce una lista di tutti i pro- 
cessi attivi; 

• get-alias: produce una lista di tutti gli alias 
definiti all'interno della shell, che permettono 
di riferirci ad un cmdlet attraverso un nome 
più corto. 

Sarebbe davvero un'impresa descrivere nei det- 
tagli tutti i cmdlet disponibili, soprattutto per- 
ché, anche considerando quelli "di poco conto", 
la maggior parte d'essi va studiato a fondo prima 
di poterne fare un utilizzo proficuo. Per non 
disperdere le nostre "energie" quindi, concentre- 



► 98 /Settembre 2006 



http://www.ioprogrammo.it 



Gestire Windows a linea di comando ■ T SISTEMA 



remo la nostra attenzione su alcuni di essi. In 
seguito, nei paragrafi successivi, vedremo qual- 
che altro Command-Let interessante. 
Prendiamo il caso del get-service. Se lanciato, 
produce un risultato del tipo: 



Status 


Name 


DisplayName 




— - 








Stopped 




Alerter Avvisi 


Running 


ALG 


Servizio 
Gateway di livello applica... 


Stopped 




AppMgmt 

Gestione applicazione 





Lanciamo ora i seguenti comandi: 

get-service | where { $_.status -eq "Running" } 
get-service | where { $_.Name -eq "Alerter" } 

Nel primo caso otterremo la lista dei soli servizi 
già avviati, mentre nel secondo solo i dettagli del 
servizio Alerter. Malgrado il secondo comando 
(ma anche il primo) si potessero ottenere in 
maniera più semplice (ad esempio, nel secondo 
caso bastava un get-service -Name "Alerter), da 
queste due righe possiamo desumere almeno un 
paio di cose. 

La prima è l'utilizzo delle pipe (identificate attra- 
verso l'utilizzo del carattere "|"). In questa 
maniera, l'output di un comando viene dato in 
pasto ad un altro e rielaborato. Sin qui, ovvia- 
mente, nulla di speciale. Ma consideriamo la 
porzione del comando 

$_.status -eq "Running" 

Il $_ identifica il generico oggetto (nel nostro caso, il 
nome di un servizio) corrente. In questa maniera, 
controllando la proprietà Status del servizio corren- 
te ed assicurandoci che sia uguale a Running, il ser- 
vizio viene aggiunto o meno nella lista finale. Questa 
"coppia di simboli" la incontreremo spesso negli 
script e pertanto è importante aver compreso bene a 
cosa si riferisca. 

Per il controllo sullo stato del servizio è stato uti- 
lizzato il -eq che equivale all'operatore d'ugua- 
glianza, uno dei più sfruttati tra quelli a disposi- 
zione. Analogamente a quanto poteva accadere 
con semplici comandi DOS, la maggior parte di 
quelli disponibili all'interno della PowerShell 
produce dei risultati tabellari (come quelli visti 
precedentemente). Spesso, però, questi risultati, 
per necessità o altro, devono essere trattati (per- 
ché magari ci occorre una lista più breve, con 
meno colonne, ecc.) e dati in pasto ad un altro 
cmdlet. Non sempre i cmdlet dispongono di 
switch in grado di fornire un risultato soddisfa- 



cente. In questi casi possiamo usare alcuni cmd- 
let adatti a questo scopo: 

• Format-List 

• Format- Custom 

• Format-Table 

• Format-Wide 

Ad esempio: 

get-service -Name "Lanmanserver"| Format-List 



.net 



Name 


lanmanserver 


DisplayName 


Server 


Status 


Running 


DependentServices : 


{Browser} 


ServicesDependedOn 


{} 


CanPauseAndContinue 


True 


CanShutdown 




True 


CanStop 




True 


ServiceType 




Win32ShareProcess 



Mentre il comando: 
Get-service | Format-Wide Name -column 3 
produce: 



Alerter 


ALG 


AppMgmt 


aspnet_state 


AudioSrv 


awhost32 


BITS 


Browser 


CiSvc 


ClipSrv 


clr_optimization_ 


_v2.0.5... 

COMSysApp 






Fig. 2: 1 cmdlet get-service, get-process e get-alias in azione. 



http://www.ioprogrammo.it 



Settembre 2006/ 99 »> 



SISTEMA T I Gestire Windows a linea di comando 



Occorre sempre fare un po' di pratica con questi 
strumenti, ma presto impareremo ad apprezzar- 
ne le potenzialità. 



POWERSHELL SCRIPTING 

Il punto di forza della nuova shell di casa 
Microsoft risiede certamente nella qualità e 
potenza dei cmdlet, che probabilmente non 
sarebbero "nulla" se non fossero affiancati da un 
altrettanto potente linguaggio di scripting. Per 
molti aspetti la sintassi delle istruzioni che pos- 
sono essere utilizzate all'interno di questi nuovi 
"batch" ricorda molto un "miscuglio" tra C++ e 
comandi DOS, anche se, rispetto a quest'ultimi, 
sono molto più flessibili da utilizzare. 
Non è certo questa la sede per poter elencare e 
spiegare tutte le istruzioni che possiamo utilizza- 
re con i programmi della PowerShell, perché non 
basterebbero queste poche righe. Tuttavia, ci 
sembra utile mostrare uno script di media com- 
plessità dal quale evidenziare un po' delle carat- 
teristiche di questi nuovi programmi. 
Il codice seguente si preoccupa di recuperare 
tutte le informazioni sulla configurazione dei 
parametri legati alla rete. Anche se può sembrare 
molto complesso, più avanti dovrebbe risultarci 
più chiaro. 



#- 



# 



#Nome file: Display_IP_Config.ps! # 



#- 



# 



#Raccolta parametri dal Registry 



#(alcuni non sono utilizzati) 

$TCPParametersKey="HKLM:\System\CurrentControl 
et\Services\tcpip\parameters" 
$DataBasePath = $(Get-ItemProperty 

$TCPParametersKey).DataBasePath 
$DeadGWDetectDefault=$(Get-ItemProperty 

$TCPParametersKey).DeadGWDetectDefault 
$DHCPDomain=$(Get-ItemProperty 

$TCPParametersKey).DHCPDomain 
$DHCPNameServer=$(Get-ItemProperty 

$TCPParametersKey).DHCPNameServer 

$DisableTaskOffload = $(Get-ItemProperty 

$TCPParametersKey).DisableTaskOffload 
$EnableSecurityFilters=$(Get-ItemProperty 

$TCPParametersKey).EnableSecurityFilters 
$ForwardBroadcasts=$(Get-ItemProperty 

$TCPParametersKey).ForwardBroadcasts 
$IPEnableRouting=$(Get-ItemProperty 

$TCPParametersKey).IPEnableRouter 
$DontAddDefaultGatewayDefault=$(Get 



ItemProperty 



$EnableICMPRedirect=$(Get-ItemProperty 

$TCPParametersKey).EnableICMPRedirect 
$Hostname=$(Get-ItemProperty 

$TCPParametersKey).Hostname 
$Domainname=$(Get-ItemProperty 

$TCPParametersKey). Domain 
$DomainNameD=$(Get-ItemProperty 

$TCPParametersKey).UseDomainNameDevolution 
$NetBTParamKey="HKLM:\System\CurrentControlSe 
\Services\netbt\parameters" 
$DHCPNodetype=$(Get-ItemProperty 

$NetBTParamKey).DHCPNodeType 
$LMhostsEnab=$(Get-ItemProperty 

$NetBTParamKey).EnableLMHosts 
#Tipo di nodo 

$DHCPTipoNodo="" 



#Tipo di nodo: 



#1 b-node 



#2 p-node 



#4 m-node 



#8 h-node 



Switch ($DHCPNodetype) 



{ 



1 {$DHCPTipoNodo="B-NODE"} 



2 {$DHCPTipoNodo="P-NODE"} 



4 {$DHCPTipoNodo="M-NODE"} 



8 {$DHCPTipoNodo="H-NODE"} 



Else {$DHCPTipoNodo= "Sconosciuto"} 



} 



#Routing abilitato? 



$IPRouting = "" 

If ($IPEnableRouting -eq 0) 

{$IPRouting = "No"} 
Else 

{$IPRouting = "SÌ"} 
#Informazioni generali. 
$OSVersion= $(Get-WMIObject 

Win32_OperatingSystem).Version 
"Windows IP Configuration" 

" Operating System Version: $OSVersion" 

Host Name : $Hostname" 

Primary DNS Suffix 

$DomainName" 

Tipo Nodo : 

$DHCPTipoNodo" 

Routing IP abilitato : $IPRouting" 

Use DNS Domain Name Devolution. . : 

$([boolean]$DomainNameD)" 

LMHosts Enabled : $([boolean] 

$LMHostsEnab)" 

DNS Suffix Search List 

$DomainName" 



$TCPParametersKey).DontAddDefaultGatewayDefault 



► 100 /Settembre 2006 



http://www.ioprogrammo.it 



Gestire Windows a linea di comando ■ T SISTEMA 



' Altri flag (0=Disabled): 



DisableTaskOffload 



$DisableTaskOffload 



EnableSecurityFilters 



$EnableSecurityFilters 



ForwardBroadcasts 



$ForwardBroadcasts 



#Informazioni x adapter. 



$ListaNetworkAdapter=Get-WMIObject 

Win32_NetworkAdapter 
$ListaNetworkAdapterConfig=Get-WMIObject 

Win32_NetworkAdapterConfiguration 
$NumeroAdapter=$ListaNetworkAdapter.Length 
For ($Cont=0; $Cont -It $NumeroAdapter; 



$Cont++) 



{ 



$NIC=$ListaNetworkAdapter[$Cont] 
$AdapterConfig = $ListaNetworkAdapterConfig[$Cont] 
#Informazioni su adapter IP Enabled 



If ($AdapterConfig.IPEnabled) 



{ 



If ($OSVersion -gt 5.0) 



{$Conn=$Nic.NetConnectionID} 



Else 



{$Conn=$NIC. Index} 



#WINS resolution attiva? 



$WINSResolution = $AdapterConfig.DNSEnabledForWi 

sResolution 



If ($WINSResolution) 



{$WINSProxy="SÌ"} 



Else 



{$WINSProxy="No"} 



Adapter: $Conn" 



Adapter type. 



$($Nic.AdapterType)" 



Description 



$($Nic. Description)" 



Physical Address. 



$($Nic.MACAddress)" 



Autoconfiguration Enabled .... : 

$($Nic.AutoSense)" 



CONFIGURAZIONE 



Connection-specific DNS Suffix . : 

$($AdapterConfig.DNSDomain)" 



DHCP Enabled 

$($AdapterConfig.DHCPEnabled)" 



IP Address. 



$($AdapterConfig.IPAddress)" 





' Subnet Mask 

$($AdapterConfig.IPSubnet)" 




' Default Gateway : 

$($AdapterConfig.DefaultIPGateway)" 




' DHCP Server : 

$($AdapterConfig.DHCPServer)" 




' DNS Servers : 

$($AdapterConfig.DNSServerSearchOrder)" 




' Proxy WINS abilitato : 

$WINSProxy" 




' Primary WINS Server : 

$($AdapterConfig.WINSPrimaryServer)" 




' Secondary WINS Server 

$($AdapterConfig.WINSSecondaryServer)" 




' Lease Obtained : 

$($AdapterConfig.DHCPLeaseObtained)" 




' Lease Expires : 

$($AdapterConfig.DHCPLeaseExpires)" 




i 








} # Fine If 




}#Fine For 



.net 



Host Nane 

Primari DNS Suffix 

Tipo Nodo 

Routing IP abilitato 

Use DNS Domain Name Deuolution. 

" "Hosts Enabled 

DNS Suffix Search List 

flag <B=Disabled>: 



Adapter type 

Description 

/100 MacPhyter PCI Adapter 

Physical Address 

Autoconfiguration Enabled . 

CONFIGURAZIONE 



DHCP Enabled. . . 
IP Address. . . . 
Subnet Mask . . . 
Default Gateway . 
DHCP Seruer . . . 
DNS Seruers . . . 
Proxy WINS abilit 
Primary UINS Seru 
Secondary UINS Se 
Lease Obtained. . 
Lease Expires . . 



Ethernet 802.3 

National Semiconductor Corp. DP83815/816 10 

0B:BD:9B:8B:A5:FB 



: True 

: 10.10.11.7 

: 255.255.255.0 

: 10.10.ii.2S4 

: 10.8.2.102 

: 10.8.2.101 10.8.2.102 

: No 

: 10.8.ES.4 

: 10.8.55.12 

: 20060612130830.000000*120 

: 20060703130830.000000*120 



Fig. 3: Output dello script programma Display_IP_Config.psl. 

Adesso cerchiamo di andare avanti analizzando 
questo codice. 



CONSIDERAZIONI 
SULLO SCRIPT 

Partiamo dalla dichiarazione delle variabili. 
Come si sarà notato, non è difficile intuire che 
per dichiarare una qualsiasi variabile è neces- 
sario anteporre il carattere $ al nome della 
variabile stessa. Ovviamente il discorso non è 
così semplice ed occorrerebbe aggiungere 



http://www.ioprogrammo.it 



Settembre 2006/ 101 ► 



SISTEMA T I Gestire Windows a linea di comando 



molto di più sull'argomento, ma per gli scopi 
di questa trattazione questo è quanto serve 
sapere. 

Già dalla dichiarazione della prima variabile, 
la $TCPParametersKey, qualcuno potrebbe 
intuire qualcosa d'importante. 
Apparentemente (e così è) contiene il riferi- 
mento ad una chiave del Registry secondo la 
sintassi HKLM:<Path To Key>. Quello che 
potrebbe essere meno chiaro è il suo utilizzo. 
Con l'introduzione della PowerShell è possibi- 
le navigare all'interno del Registry (limitata- 
mente alle chiavi HKEY_LOCAL MACHINE e 
HKEY_CURRENT_USER) come se si trattasse 
di un insieme di cartelle e sottocartelle. 
Se dalla shell digitiamo il comando HKLM: e 
successivamente lanciamo una DIR, otterre- 
mo proprio l'elenco delle chiavi principali 
della HKEY_LOCAL_MACHINE. Stesso discor- 
so per HKCU. 

Tornando quindi al nostro script, abbiamo 
visto quindi che la $TCPParametersKey con- 
tiene proprio il riferimento alla chiave del 
Registry che memorizza alcune delle informa- 
zioni sulla configurazione di rete. 
L'istruzione successiva utilizza questo dato in 
un modo che evidenzia la potenza della sin- 
tassi e dei comandi del nuovo linguaggio di 
scripting: 

$DataBasePath=$(Get-ItemProperty 

$TCPParametersKey).DataBasePath 

Innanzitutto cominciamo dal cmdlet Get- 
ItemProperty Questo command-let consente di 
recuperare informazioni su di un file o comun- 
que su un oggetto permettendo di poterle tratta- 
re in seguito opportunamente. Per comprendere 
meglio il suo funzionamento ci avvarremo di un 
esempio che mostri realmente quello che acca- 
de. 
Dalla PowerShell lanciamo il comando: 

Get-ItemProperty 

"HKLM:\System\CurrentControlSet\Services\tcpip\ 

paameters" 

Il risultato sarà qualcosa del tipo: 

PSPath 

Microsoft. PowerShell. Core\Registry::HKEY_LOCAL_MA 

CHINE\ 
System\CurrentControlSet\Services\tcpip\parameters 
PSParentPath : 

Microsoft. PowerShell. Core\Registry::HKEY_LOCAL_MA 

CHINE\ 
System\CurrentControlSet\Services\tcpip 
PSChildName : parameters 



PSDrive : HKLM 


PSProvider : 

Microsoft. PowerShell. Core\Registry 


NV Hostname : PRESARIO 


DataBasePath : 

C:\WINDOWS\System32\drivers\etc 


NameServer 




ForwardBroadcasts 





IPEnableRouter 





Domain 




Hostname 


PRESARIO 


SearchList : 

My Domain, MyDomain.it 


UseDomainNameDevolution 


1 


EnableICMPRedirect 


1 


DeadGWDetectDefault 


1 


DontAddDefaultGatewayDefault 





EnableSecurityFilters 





DisableTaskOffload 





PerformRouterDiscovery : 


DhcpNameServer : 10.0.0.101 

10.0.0.102 


DhcpDomain yDomain.it. 



Arrivati sin qui, non dovrebbe essere molto 
difficile capirne la logica. Il Get-ItemProperty 
ritorna l'oggetto che rappresenta l'entry alla 
chiave del Registry come un'entità con delle 
proprietà (pari alle sottochiavi trovate) e le 
utilizza per memorizzarne le impostazioni. 
Apparentemente complicato, ma estrema- 
mente flessibile. 

In questo modo lo script può recuperare dal 
registro di Windows tutte le impostazioni di 
cui necessita. Andando avanti s'incontra un 
costrutto che ricorda molto il linguaggio C: il 
costrutto SWITCH. Esso può essere visto più 
come una classica SELECT che come una 
variante del costrutto IF. Il suo funzionamen- 
to è semplice e non sprecheremo ulteriore 
spazio. Appena all'inizio della sezione 
Informazioni generali notiamo un'altra 
importante novità: il cmdlet Get-WMIObject. 
Questo cmdlet è tra quelli che probabilmente 
incontreranno il consenso della maggior 
parte degli sviluppatori di script e batch per- 
ché permette di ridurre drasticamente il 
numero di linee di codice che sfrutta WMI. 
Come fatto in precedenza, partiremo da un 
esempio: 

Get-WMIObject Win32_OperatingSystem 

produce a video qualcosa del tipo: 



SystemDirectory 


: C:\WINDOWS\system32 


Organization 


: Bull Italia Spa 


BuildNumber 


: 2600 



► 102 /Settembre 2006 



http://www.ioprogrammo.it 



Gestire Windows a linea di comando |i ▼ SISTEMA 



quella corrente, (ad esempio F:\PowerShell 
Scripts) sarà sufficiente lanciare un comando 
simile a: 



Forti delle considerazioni precedenti, il comando: &"F:\PowerShellScripts\DisplayiPConfig" 



RegisteredUser 


: Francesco Lippo 


SerialNumber 


: lllll-OEM-2222222-33333 


Version 


: 5.1.2600 



(Get-WMIObject Win32_OperatingSystem). Version 

non potrà che produrre come output la stringa 
5.1.2600 (importantissimo l'uso delle parentesi 
per delimitare la classe a cui WMI dovrà far rife- 
rimento). Se qualcuno è pratico di program- 
mazione di script e faceva uso tempo fa di 
WMI, ricorderà certamente che produrre lo 
stesso risultato con lo stesso numero di righe, 
appena visto, è praticamente impossibile. 
Andando ancora avanti nell'esame dello 
script, osserviamo che recupera anche la ver- 
sione del sistema operativo installata. Per 
inciso, prima di proseguire, aggiungiamo che, 
se avessimo voluto memorizzare solo le prime 
cifre del campo Version (prive cioè del 
BuildNumber), avremmo dovuto semplice- 
mente considerare: 

$(Get-WMIObject 

Wìn32_OperatingSystem). Version. Su bst ring (0,3) 

Adesso, spostiamo la nostra attenzione nella 
sezione Informazioni x adapter. Le due istruzioni 
seguenti 

$Listal\letworkAdapter=Get-WMIObject 

Win32_NetworkAdapter 
$Listal\letworkAdapterConfig=Get-WMIObject 

Win32_NetworkAdapterConfiguration 

si preoccupano di recuperare l'elenco dei 
network adapter e della relativa configurazio- 
ne di rete. Poiché l'elenco potrebbe essere 
piuttosto lungo, il ciclo FOR-NEXT successivo 
effettua il controllo soltanto sui device IP 
Enabled, scartando i restanti. Il funzionamen- 
to del ciclo dovrebbe essere abbastanza intui- 
tivo e non verrà aggiunto altro in merito. 
Prima di passare alle conclusioni, ancora 
qualche piccola considerazione. Sinora non 
abbiamo fatto cenno all'avvio dei propri 
script dalla PowerShell. Se ad esempio il 
nostro file si chiama DisplayIPConfig.ps 1 e si 
trova nella stessa directory in cui siamo al 
momento, è sufficiente lanciare uno qualun- 
que di questi comandi: 

.\DisplayIPConfig 

./DisplaylPConfig 

L'estensione PS1 non è necessaria. Invece, nel 
caso il file si trovi in una directory diversa da 



Dedichiamo ancora qualche istante ad un cmd- 

let che potrebbe passare inosservato: Get-mem- 

ber. 

Questo command-let consente di recuperare 

proprietà e metodi di qualunque oggetto in 

maniera molto semplice. 

Vediamone subito un piccolissimo esempio: 

Get-Service | Get-Member 

produce qualcosa del tipo: 



Name 




MemberType Definition 
















Name 






AliasProperty 
Name = ServiceName 


add_Disposed 

Systenr 


.Void add_ 


Method 
_Disposed(EventHandle... 


Close 






Method 
System. Void Close() 


Continue 






Method 
System. Void Continue() 




CanPauseAndContinue Property 

System. Boolean CanPauseAndContinue {... 


CanShutdown 

System. Bool 


Property 
ean CanShutdown {get;} 


CanStop 




System 


Property 

.Boolean CanStop {get;} 


Container 


System 


Property 
ComponentModel.IContainer Con... 



Inutile ribadire che queste informazioni possono 
tornarci utili nei nostri script e pertanto è davve- 
ro importante comprendere la validità di questo 
cmdlet. 



CONCLUSIONI 

Non potevamo non concludere questo artico- 
lo con un'affermazione più che ovvia: e non 
finisce qui. La PowerShell farà sicuramente 
parlar di sé per molto tempo e certamente 
non potranno che essere per la maggior parte 
critiche positive. Chiunque decida di avventu- 
rarsi in questo nuovo mondo scoprirà presto i 
vantaggi in termini di versatilità e potenzialità 
offerte dal nuovo linguaggio di scripting e non 
potrà più farne a meno. 

Francesco Lippo 



http://www.ioprogrammo.it 



Settembre 2006/ 103 ► 



SISTEMA T Le soluzioni ottimali per problemi frequenti 



SINGLETON PATTERN 
COME USARLO? 

NON MOLTI CONOSCONO QUESTA TECNICA DI PROGRAMMAZIONE. TUTTAVIA SI TRATTA DI 
UN TASSELLO FONDAMENTALE PER NON INCIAMPARE IN OGGETTI DUPLICATI E STRUTTURE 
POCO EFFICIENTI. IMPARIAMO COSA È E COME FUNZIONA 




Nel precedente appuntamento abbiamo 
avuto modo di discutere cosa sia un pat- 
tern e quale sia la sua utilità, analizzando 
il pattern Observer. Questa volta descriveremo 
l'utilizzo di un altro tipo di pattern: il singleton. 
Ricordiamo brevemente che i pattern sono in 
sostanza soluzioni standard a delle problemati- 
che frequenti in campo software. Essi si basano 
principalmente sulla programmazione orientata 
agli oggetti (OOP) e mirano a migliorare la qua- 
lità del codice agendo su caratteristiche legate ad 
essa. Ad esempio mirano ad aumentare la riusa- 
bilità del codice, ad aumentare il livello di inca- 
psulamento delle informazioni e a diminuire il 
livello di coesione tra oggetti di classi differenti. 
Il singleton è un modello di realizzazione di una 
classe che prevede la centralizzazione di un certo 
tipo di operazioni, attraverso l'utilizzo di un'i- 
stanza di un oggetto, che sia unica all'interno del 
programma, e per tutto il ciclo di vita del pro- 
gramma. In altre parole si utilizza un singolo 
oggetto per determinate operazioni, ma: 



A scapito della semplicità della struttura di un 
singleton, il cui diagramma UML è riportato in 
FIGURA, la sua utilità è davvero elevata. Vediamo 
ad esempio una problematica concreta, in cui 
applicare questo pattern porta a una soluzione di 
qualità elevata. 



LA PROBLEMATICA 

Supponiamo di volere implementare in una 
nostra applicazione una funzionalità di log- 
ging. Il "log" di un programma, come noto, è 
generalmente un file di testo contenente una 
sequenza di stringhe descrittive dell'attività 
svolta dal programma stesso. A ciascuna di 
queste stringhe è associato un "timestamp" 
ovvero una stringa contenente l'istante preci- 
so nel quale l'evento che è descritto nel log si 
è verificato. Quello che segue, ad esempio, è 
un estratto del file di log del firewall software 
installato sul PC di chi scrive: 



fì 




REQUISITI 



u 



Basi di C++ 



ì 



Un qualunque 
compilatore C+ 




• non ci possono essere due oggetti di questo 
tipo 

• questo oggetto si può creare una volta sola- 
mente 

• gli altri oggetti accedono alle funzionalità del 
singleton, che quindi ha accesso unico alla 
risorsa che gestisce 





Singleton 








^>$ instance : Singleton 




^SingletonQ 
^getlnstanceQ : Singleton 




N 


- 


s s 






Singleton getlnstanceQ ^ 

{ 

if(instance == nuli) 
instance = new SingletonQ; 

return instance; 

} 















06/29/2006 20:24:49 Blocked ICMP Incoming 
150.101.120.105 3 192.168.1.103 
06/29/2006 20:24:49 Allowed ICMP Incoming 
150.101.120.105 3 192.168.1.103 
06/29/2006 20:24:49 Allowed UDP Incoming 
192.168.1.103 138 192.168.1.255 
06/29/2006 20:24:49 Allowed UDP Outgoing 
192.168.1.255 138 192.168.1.103 



Si può notare la presenza di informazioni più 
o meno utili, come ad esempio se il pacchetto 
di rete è in ingresso o uscita (Incoming/ 
Outgoing), se è stato o meno bloccato 
(Allowed/Blocked) ecc. All'inizio di ciascuna 
riga vi è il timestamp che permette di capire 
quando si è verificato un dato evento, al fine 
di ricostruire eventuali situazioni anomale o 
correggere errori nella configurazione del 
programma. 

È evidente che la funzionalità di logging va al 
di là di una semplice stampa di una stringa. 



► 104 /Settembre 2006 



http://www.ioprogrammo.it 



Le soluzioni ottimali per problemi frequenti HI T SISTEMA 



Infatti si va incontro a diverse problematiche: 

• deve essere aperto un file in scrittura 

• a ogni stringa che si stampa deve essere 
associata una data e un orario 

• la stampa deve essere fatta in maniera 
automica, cioè non ci devono essere 
sovrapposizioni di stringhe se due oggetti 
"loggano" contemporaneamente 

• la stampa non deve inficiare le prestazioni 
dell'applicazione o causarle problemi 

• ecc. 

Date queste caratteristiche è ragionevole pen- 
sare di incapsulare le varie funzionalità di log- 
ging all'interno di una classe. L'istanza di 
questa classe, che verrà realizzata come un 
singleton, costituirà l'unico e solo punto di 
accesso di un qualsiasi oggetto della nostra 
applicazione alle funzionalità di logging. 



LA SOLUZIONE 
IL SINGLETON 

Una possibile classe che risolva il nostro pro- 
blema è la seguente: 

// log-h 

#ifndef LOG_H 
#define LOG_H 

#include <list> 
#include <string> 

class Log { 
public: 

void Scrivi(const char* linea); 

bool Salva(const char* nomefile); 
private: 

std: :list<std: :string> m_data; 

}; 

#endif 



list<string> 


:iterator la 


stlt= 


= m_data.end(); 


for (it=m_data.begin() 


it! = 


lastlt; 


+ + it) 


file << *it 


<< endl; 








file.close(); 


} 



Questa classe fornisce a tutti gli effetti le varie 
funzionalità di scrittura di un log, anche se 
risulta un po' naif come implementazione (ad 
esempio manca il timestamp ed è necessario 
salvare "manualmente" il file di log chiaman- 
do la funzione SalvaO). 

Tuttavia il principale difetto di questa realiz- 
zazione è che essa accorpa le funzionalità 
richieste in un'unica classe ma NON in un'u- 
nica istanza di quella classe. In altre parole è 
possibile istanziare quanti oggetti di tipo Log 
si vuole, senza alcun vincolo. Questo è in con- 
traddizione con quanto detto sinora sulla 
bontà del pattern Singleton, per cui ora modi- 
ficheremo il codice di questa classe in manie- 
ra tale che essa risponda alle nostre esigenze. 
Per fare in modo che un oggetto di tipo Log 
venga istanziato una e una sola volta è possi- 
bile utilizzare il meccanismo delle variabili 
statiche del C++. Ricordiamo brevemente che 
anteponendo, nella dichiarazione di una 
variabile, la parola chiave "static" si istruisce 
il compilatore a fare in modo che la variabile 
in questione sia dichiarata solo la prima volta 
che quel codice viene eseguito. 
Potremmo quindi scrivere: 



class Log { 


public: 


static void 


Scrivi(const char* 


linea); 


static bool Salva(co 


nst char* 


nomefile); 


private: 


static std: 


list<std: 


:string> m_data; 


}; 




E nel file Log.cpp aggiungere: 



// log.cpp 



#include <fstream> 



using namespace std; 



#include "log.h" 



void Log: :Scrivi(const char* linea); 

{ 

m_data.push_back( linea); 



} 



std: :list<std: :string> Log: :m_data; 

Abbiamo reso statiche le dichiarazioni di fun- 
zione e la variabile della classe Log che imma- 
gazzina le stringhe da stampare. Un metodo 
statico di una classe può essere utilizzato 
senza istanziare l'oggetto della classe stessa, 
utilizzando l'operatore "::" : 

Log: :Scrivi("Ciao!"); 



bool Log: :Salva(const char* nomefile); 



{ 



ofstream file(nomefile, ios::out); 



list<string> : :iterator it; 



La variabile membro m_data viene invece 
istanziata direttamente nel file .cpp nel quale 
sono implementate le funzioni. 
Questa soluzione da una parte soddisfa i 



http://www.ioprogrammo.it 



Settembre 2006/ 105 ► 



SISTEMA T I Le soluzioni ottimali per problemi frequenti 




nostri requisiti, dall'altra però risulta poco 
flessibile sotto altri punti di vista. Ad esempio 
il fatto che il membro sia statico rende diffici- 
le controllarne l'inizializzazione e la distru- 
zione, affidando quasi completamente al 
compilatore il compito di posizionare queste 
due fasi all'interno del ciclo di esecuzione 
dell'applicazione. 

Un altro svantaggio risiede nel fatto che utiliz- 
zare metodi statici impedisce di utilizzare una 
delle caratteristiche più interessanti della 
programmazione a oggetti, e cioè il polimorfi- 
smo, attraverso l'uso di funzioni "virtuali". 



SINGLETON 
POLIMORFICO 

Le funzioni virtuali del C++ (cioè le funzioni di 
una classe dichiarate con la parola chiave "vir- 
tual") servono ad attuare il meccanismo del "late 
binding". Questo meccanismo consente di deci- 
dere a run-time, cioè durante l'esecuzione del 
programma, quale sia il metodo corretto da 
richiamare. Questo è l'opposto dell' "early bin- 
ding" in cui la decisione viene fatta al momento 
della compilazione del codice. 
Supponiamo ad esempio di volere realizzare due 
differenti tipi di log, uno che viene salvato su file 
e l'altro che invece viene inviato via rete a una 
macchina remota, attraverso una connessione 
TCP. Le funzioni ScriviO e SalvaO saranno 
senz'altro comuni ai due tipi di log, mentre il log 
che effettua la connessione avrà bisogno di ulte- 
riori informazioni per potere essere utilizzato, ad 
esempio l'indirizzo IP della macchina remota. 
Per realizzare questo meccanismo possiamo 
astrarre le funzionalità comuni ai due tipi di log, 
inserendoli in una classe base astratta. 
Successivamente creiamo due classi derivate, 
che implementano le funzionalità comuni e 
aggiungono, all'occorrenza, le ulteriori funziona- 
lità richieste: 



// Log.h 


class Log { 


public: 


virtual ~Log () {} 


virtual void 


Scrivi(const char* 


linea) = 0; 


virtual bool 


Salva(const char* 


nomefile) = 0; 


}; 




// LogFile.h 


class LogFile 


: public Log { 




public: 


virtual ~LogFile(); 


virtual void 


Scrivi(const char* 


linea); 


virtual bool 


Salva(const char* 


nomefile); 



private: 


std: :list<std: :string> m 


_data; 






}; 




// LogNetwork.h 


class LogNetwork : public 


Log { 






public: 


virtual ~LogNetwork(); 


virtual void Scrivi(const 


char* 


inea); 




virtual bool Salva(const 


char* 


nomefil 


e); 


virtual void ImpostaPCRemotoi 
TCPCo 


const 
-inectio 


n& server); 


private: 


TCPConnection m_logServer; 


std: :list<std: :string> m 


_data; 






}; 



In questo esempio la classe base astratta Log 
contiene le due funzioni virtuali pure (cioè non 
implementate) SalvaO e ScriviO- LogFile e 
LogNetwork sono le classi derivate che imple- 
mentano il codice di queste funzioni, ciascuna 
con le sue peculiarità. Ad esempio LogFile farà 
un accesso a disco per salvare il contenuto del 
log, mentre LogNetwork invierà la richiesta di 
salvataggio tramite rete al PC remoto. Da notare 
come il distruttore della classe base debba essere 
dichiarato anch'esso come "virtual", per permet- 
tere all'oggetto istanziato di utilizzare il proprio 
distruttore anziché quello della classe base. 
In definitiva, riprendendo il discorso precedente, 
possiamo beneficiare di un meccanismo impor- 
tante come quello del polimorfismo anche utiliz- 
zando il pattern singleton. Per fare questo tutta- 
via dobbiamo rinunciare all'utilizzo di metodi e 
membri statici. 
Vediamo quindi come aggirare questo problema. 



IL CODICE 

Il trucco per evitare di rendere tutte le funzio- 
ni del singleton statiche, consiste nell'utiliz- 
zare il meccanismo statico solamente in fase 
di creazione del singleton. La creazione non 
avviene tramite un normale costruttore, ma 
tramite una particolare funzione, chiamata 
IstanzaO, che restituisce un puntatore valido 
all'oggetto singleton. IstanzaO deve essere di 
tipo statico, in quanto deve essere chiamata 
prima della creazione del singleton, creazione 
della quale si occupa essa stessa. Applicando 
questi concetti alla nostra classe di esempio 
otteniamo: 

class Log { 

public: 



► 106 /Settembre 2006 



http://www.ioprogrammo.it 



Le soluzioni ottimali per problemi frequenti HI ▼ SISTEMA 



static Log* InstanzaQ { 



if (!m„plnstance) 



m_plnstance = new Log(); 



return m_plnstance; 



} 



void Scrivi(const char* linea); 



bool Salva(const char* nomefile); 



private: 



Log(); 



Log(Log const&); 



static Log* m_plnstance; 



static std: :list<std: :string> m_data; 



}; 



// in log.cpp 



Log* Log: :m_plnstance = NULL; 

La funzione IstanzaO controlla se il puntatore 
all'oggetto Log m_plnstance è NULL oppure no. 
Se è NULL, cioè se è la prima volta che IstanzaO 
viene chiamata, l'oggetto viene creato e ne viene 
restituito il riferimento. In caso contrario viene 
restituito il riferimento memorizzato in prece- 
denza. Un esempio di utilizzo di questa classe è il 
seguente: 

Log: : IstanzaQ- > Seri vi ("Ciao!"); 
Log: : Istanza()- >Salva("log.txt"); 

La prima chiamata a IstanzaO provocherà la 
creazione dell'oggetto Log, sul quale verrà richia- 
mata la ScriviO. La seconda chiamata a IstanzaO 
utilizzerà il riferimento creato in precedenza per 
richiamare la Salva(). 

Una cosa fondamentale da notare è che sia il 
costruttore che il costruttore di copia sono 
dichiarati nella parte privata della classe. Questo 
impedisce di ottenere un riferimento all'oggetto 
se non attraverso la funzione IstanzaO. In altre 
parole non è possibile scrivere: 

Log* miojog = new Log(); //NO! 

poiché il costruttore è accessibile solamente 
al codice della classe Log stessa, ma non all'e- 
sterno. Un'altra cosa che non è possibile fare 
è effettuare una copia diretta di un oggetto di 
tipo Log: 

Log miojog = *(Log: :Istanza()); //NO! 

Se ciò fosse possibile si avrebbe un metodo per 
costruire quanti oggetti vogliamo senza passare 
attraverso IstanzaO, creando in questo modo più 
di un oggetto Log, cosa che è incompatibile col 
concetto stesso di Singleton. 
Un appunto che può essere mosso alla particola- 



re realizzazione del pattern singleton che abbia- 
mo esposto sinora è che esso può creare dei 
"memory leak", cioè "sprechi di memoria". Non 
essendo possibile controllare direttamente la 
distruzione del singleton, questo rimarrà in 
memoria anche quando non sarà utilizzato. 
Questo problema tuttavia concerne molto più la 
definizione di "memory leak" che la realizzazio- 
ne del pattern. Se infatti consideriamo un 
memory leak come la presenza di memoria non 
deallocata direttamente dal software, allora 
abbiamo, nel nostro caso, un memory leak. Se 
invece consideriamo un memory leak come l'esi- 
stenza di una generica memoria non più control- 
labile, allora NON siamo in presenza di un 
memory leak, poiché il nostro singleton "vive" 
per tutta la durata dell'esecuzione del software. 
La memoria viene "sprecata" unicamente nel 
momento in cui l'esecuzione termina. Tuttavia 
nella maggior parte dei sistemi operativi TUTTA 
la memoria allocata per un processo viene libe- 
rata nell'istante stesso in cui quel processo ter- 
mina, e viene resa disponibile per altre operazio- 
ni. Quindi tecnicamente lo spreco di memoria 
non avviene mai. 



CONCLUSIONI 

Il pattern singleton è molto utile in tutti quei 
casi in cui si ha bisogno di centralizzare una 
serie di funzionalità all'interno di una archi- 
tettura software. Questo può avvenire ad 
esempio quando si ha a che fare con una 
risorsa unica, di tipo sia logico, ad esempio il 
file di log dei nostri esempi, che fisico come 
ad esempio la memoria della scheda video o 
una particolare periferica. Abbiamo visto che 
in C++ la realizzazione del pattern singleton 
passa attraverso due concetti base: 

• l'utilizzo di una funzione statica IstanzaO 
che si occupa di restituire un riferimento 
valido al singleton 

• la dichiarazione di costruttore e costruttore 
di copia come metodi privati della classe 
cui si riferiscono 

I singleton sono spesso utilizzati anche nella 
realizzazione di librerie o kit di sviluppo 
software, per cui è bene conoscerne la natura, 
sia per utilizzarli al meglio sia per progettare 
noi stessi delle librerie di qualità. Inoltre lo 
incontrerete spesso nell'utilizzo di particolari 
librerie o framework esterni poiché si tratta di 
uno dei pattern più usati in programmazione 




Alfredo Marroccelli 



http://www.ioprogrammo.it 



Settembre 2006/ 107 ► 



SOFTWARE SUL CD T ■ Librerie e Tool di sviluppo 



SUL CD 



Flex 2.0 

IL NUOVO FRAMEWORK DI ADOBE 

Straordinario! Non ci sono parole per 
descrivere questo nuovo prodotto della 
linea Adobe che in un sol colpo fa piaz- 
za pulita di un vecchio modo di pensare 
alle applicazioni per inventarne uno 
tutto nuovo, semplice ed estremamente 
potente. Chi ha letto questo numero di 
ioProgrammo sa già come funziona Flex 
2.0. Si scrive un programma utilizzando 
un dialetto di XML, lo si da in pasto al 
compilatore e si ottiene in uscita un file 
SWF ovvero utilizzabile dal noto player 
Flash di macromedia. Quali sono i van- 
taggi? Ce ne sono diversi, i più facili da 



intuire sono la completa indipendenza 
dal sistema operativo senza per questo 
doversi affidare alla macchinosità di 
java. La possibilità che la stessa applica- 
zione possa girare praticamente senza 
modifiche sia in modo standalone che 
nel browser. La possibilità di sviluppare 
interfacce complesse come quelle che 
siamo abituati a vedere in flash e tali 
che conservino lo stesso aspetto e com- 
portamento su praticamente ogni siste- 
ma operativo. Dal punto di vista esclusi- 
vamente funzionale rispetto alla classi- 
ca programmazione Flash le innovazioni 



sono importanti. L'interazione con i 
database è di una facilità estrema, c'è 
una completa indipendenza del codice 
dal layout, i programmatori hanno a 
disposizione una gamma di strumenti 
veramente ampia per poter svolgere il 
loro lavoro. Si tratta dunque di un pro- 
dotto decisamente innovativo, assoluta- 
mente da provare. In questo numero di 
ioProgrammo pubblichiamo un articolo 
che vi metterà subito in grado di utiliz- 
zare il prodotto e di intuirne le straordi- 
narie possibilità 
Directory:/FLex 



AJAXPRO 
STARTER KIT 

PER INIZIARE FACILMENTE 
CON VISUAL STUDIO 

Da qualche tempo non si fa altro che 
parlare di Ajax. Si tratta della nuova tec- 
nologia che consente di realizzare pagi- 
ne web dinamiche che non necessitano 
del reload per aggiornare i dati. Come 
potete intuire si tratta di un'innovazione 
senza precedenti che consente di realiz- 
zare applicazioni Web con comporta- 
menti molti simili alle normali applica- 
zioni Desktop. Visual Studio 2005 dispo- 
ne della tecnologia degli Starter Kit, che 
consentono di iniziare un progetto par- 
tendo da una sorta di template che ne 
facilità l'avvio. Il tool che vi presentiamo 
è appunto lo starter kit che consente di 
iniziare a sviluppare un progetto Web in 
ASP.NET ed in tecnologia AJAX. Si tratta 
senza dubbio di un valido aiuto per 
coloro che vogliono sviluppare le pro- 
prie Web Application 
Directory :/AjaxProStarterKit 



ASCEND.NET 
WINDOWS FORM 

UN'UTILE COLLEZIONE 
DI CONTROLLI 

Si tratta di una serie di controlli da inte- 
grare in Visual Studio.NET come non se 
ne vedeva da tempo. All'interno di que- 
sta libreria trovano spazio 6 nuovi com- 
ponenti. In particolare: un gradient 
Panel, un gradientCaption, un gradient 
SplitBar, un gradientNavigationButton, 
un gradientAnimation Pane image e 
infine un Navigation Pane. Tutti compo- 
nenti tesi a migliorare l'aspetto estetico 
di un'applicazione aggiungendovi quel- 
la morbidezza che favorisce un miglior 
rapporto fra l'utente ed il software 
Directory :/AscendNet 

COMMERCE 
STARTER KIT 1.0.0.3 

IL TEMPLATE PER PAYPAL 

Con il nome in codice CSK, questo star- 
ter kit contiene un template per lo svi- 
luppo di un sito di commercio elettroni- 



co con interfaccia verso paypal. Scritto 
per la versione 2.0 di Asp.NET si confi- 
gura come un prodotto completo dotato 
di tutti gli elementi classici di un negozio 
di commercio elettronico, dal più classi- 
co dei carrelli fino alla gestione del cata- 
logo e degli ordini. Rimane ovviamente 
uno starter kit, quindi è compito del 
programmatore personalizzare il com- 
portamento dei singoli task. E questo 
per noi sviluppatori è ulteriore motivo di 
interesse, non si tratta infatti solo di un 
prodotto pronto all'uso ma di un punto 
di partenza in grado di essere adattato 
ala proprie esigenze 
Directory :/commercestarterkit 

ATLAS 

CONTROL TOOLKIT 

I MIGLIORI COMPONENTI 
PER IL WEB 

Nasce da una collaborazione fra 
Microsoft e i creatori originali, questo 
interessante pacchetto che si propone di 
fornire al programmatore una serie di 



► 108 /Settembre 2006 



http://www.ioprogrammo.it 



Librerie e Tool di sviluppo ■ T SOFTWARE SUL CD 



componenti "client" adatti a favorire lo 
sviluppo di Web Application. All'interno 
del pacchetto si trova una ricca collezio- 
ne di esempi che fanno uso di una quin- 
dicina di nuovi controlli, infine c'è un 
SDK che consente di estendere ulterior- 
mente Atlas che in questo modo si con- 
figura come un vero e proprio 
Framework per lo sviluppo 

ECLIPSE 3.2 

ADESSO PUOI SVILUPPARE 
ANCHE IN FLASH 

In moltissimi già conoscono Eclipse con 
l'IDE più utilizzato dai programmatori 
Java, tanti altri lo hanno esteso per le 
proprie esigenze. In molti lo utilizzano 
per PHP o per C++, e chi ha letto l'arti- 
colo su "Flex 2.0" presente in questo 
stesso numero di ioProgrammo, saprà 
adesso che è possibile utilizzare Eclipse 
anche per sviluppare applicazioni mxml 
cioè in un linguaggio che una volta com- 
pilato restituisce dei normai file SWE 
E con questo la maturità raggiunta da 
Eclipse diventa ormai completa, tanto 
che non esiste linguaggio, problematica 
o applicazione che non possa essere in 
una qualche maniera, senza dubbio 
ottimale, affrontata con Eclipse. 
Davvero un bel salto in avanti per que- 
sto progetto, che nel tempo è diventato 
un punto di riferimento per un'intera 
comunità 
D i rectory ://Ecl i pse 

DEVCPP 4.9.2 

IL PIÙ AMATO DAI 
PROGRAMMATORI C++ 

Da qualche tempo non faceva capoli- 
no fra le nostre pagine questo interes- 
santissimo IDE per programmatori 
C++. Sicuramente si tratta di uno degli 
ambienti più amati dai programmato- 
ri di questo linguaggio. Dalla sua 
parte un'incredibile leggerezza che lo 
rende utilizzabile su macchine anche 
non eccezionalmente performanti, e 
poi tutta una serie di features che 
vanno dal code complexion alla sintax 
highlightinhg, ma non solo. Si tratta di 
un software completo che esteso con 
plugin diventa anche un editor RAD 
con interfaccia visuale. ioProgrammo 
spesso lo usa come editor di riferi- 
mento 
Directory://devcpp 



ECLIPSE MODELIIMC 
FRAMEWORK 

IL TOOL PER PRODURRE CLASSI 
A PARTIRE DA UN MODELLO 

Eclipse fa riferimento a questo fra- 
mework quasi per ogni operazione che 
ha necessità di svolgere. Si tratta si un 
tool che consente di generare delle clas- 
si partendo da un modello specificato in 
formato XML I modelli possono essere 
generati utilizzando un qualunque tool 
e qualunque applicazione supporti il 
formato EMF sarà in grado di condivide- 
re le stesse informazioni. Si tratta dun- 
que di un progetto che ha una parte 
importante in Eclipse ma che può esse- 
re utilizzato in modo conveniente per la 
risoluzione di tutta una serie di proble- 
mi 
Directory :/Eclipse 

GRAPHICAL EDITING 
FRAMEWORK 

IL PLUGIN PER FAR DIVENTARE 
ECLIPSE RAD 

Non si tratta di un RAD completo ma di 
un framework a cui Eclipse può appog- 
giarsi per creare ambienti RAD per i lin- 
guaggi supportati. Supponete per esem- 
pio di voler costruire un plugin di 
Eclipse che consenta di creare un 
ambiente RAD per lo sviluppo in 
PYTHON. Dove per RAD si intende un 
ambiente dotato di editor visuale che vi 
metta in grado di creare interfacce tra- 
scinando gli elementi su una Form. Per 
far questo avete bisogno di GEF che vi 
mette a disposizione tutti gli strumenti 
per trasformare il vostro IDE preferito in 
un RAD leggendo la descrizione del 
modello a partire da un file XML. GEF 
ad esempio è indispensabile per instal- 
lare FlexBuilder, l'IDE RAD per flex 
Directory:/gef 

HIBERNATE 3.2.0 

TRASFORMA I DA DATI 
DA SQL AD OGGETTI 

Ormai lo sappiamo abbiamo letto tutti 
gli articoli di ioProgrammo su 
Hibernate, pensare in termini di query 
e dati SQL non è più conveniente! 
Disponiamo di oggetti e di classi, non 
possiamo continuare a lavorare in 
modo disomogeneo trattando i dati 
SQL in maniera separata dal resto del 
flusso del programma. E per mappare i 
dati da SQL ad oggetti abbiamo biso- 



gno di un tool. Il primo ed ancora 
adesso Leader di questo settore è 
Hibernate, attraverso il quale riuscia- 
mo ad ottenere comodamente i risul- 
tati voluti 
Directory:/ Hibernate 

OPEMLASZLO 3.3.1 

L'ALTERNATIVA OPENSOURCE 
A FLEX 

A Flex dedichiamo veramente tantissi- 
mo spazio in questo numero di 
ioProgrammo. Sappiamo già che è un 
compilatore grazie al quale è possibile 
ottenere applicazioni Flash partendo da 
un file descrittivo in XML. Sappiamo 
anche che il Flex SDK è gratuito, allo 
stesso modo FlexBuilder ovvero l'editor 
per Flex ha un costo! Non è un grande 
problema, in quanto l'uso dell'editor 
non è vincolante per poter scrivere i pro- 
grammi, tuttavia è comunque un vinco- 
lo. Ed ecco arrivare Ide4laszlo, alternati- 
va OpenSource a Flex che ha dalla sua 
parte oltre la gratuità degli strumenti, 
anche la possibilità di ottenere interfac- 
ce DHTML anziché Flash. 
Si tratta di un buon prodotto a cui sicu- 
ramente dedicheremo spazio nelle 
nostre pagine 
Directory:/ ide4laszlo 

PHP 5.1.4 

IL LINGUAGGIO DI INTERNET 

Se seguite ioProgrammo o più semplice- 
mente siete dei programmatori Web, o 
ancora molto più semplicemente navi- 
gate su Internet, non potete non sapere 
che cosa è PHP Si tratta del linguaggio 
con il quale sono sviluppate la maggior 
parte delle applicazioni internet esisten- 
ti. Quasi tutto il software per il web si 
regge su PHP La curva di apprendimen- 
to è bassissima, le funzionalità esposte 
elevatissime, certamente se avete inten- 
zione di sviluppare per il web non potre- 
te fare a meno di provare anche questo 
linguaggio come base per le vostre 
applicazioni. Attualmente la versione 
5.1.4 espone un modello ad oggetti piut- 
tosto completo che rende PHP un lin- 
guaggio moderno dalla curva di appren- 
dimento molto rapida e persino didatti- 
co per chi vuole imparare a programma- 
re ad oggetti senza dover affrontare la 
complessità di fava o .NET. Ed è in arrivo 
lo Zend Framework... 
Directory PHP 5.1.4 



http://www.ioprogrammo.it 



Settembre 2006/ 109 ► 



SOLUZIONI T ■ Sicurezza dei dati 



CRITTOGRAFIA 
ASIMMETRICA 

DALL'ALGORITMO DI MERKLE HELLMAN, ALLA CRITTOGRAFIA RSA , PASSANDO IL METODO 
DEL PUZZLE E DI BLUM GOLDWASSER, ESPLORIAMO GLI ALGORITMI DI CRITTOGRAFIA 
ASIMMETRICA CHE CONSENTONO LO SCAMBIO SICURO DI DATI, CHE TENTANO DI FARLO 




n 




REQUISITI 



n.».wmi; 



— Basi di crittografia 






Tempo di realizzazione 



00000 



Il modo di affrontare un problema ne individua la 
tecnica. Tra queste pagine abbiamo esplorato mol- 
te delle tecniche utilizzate nel mondo della pro- 
grammazione. ÈMolte trattazioni degli scorsi appun- 
tamenti convergono verso l'affascinante mondo dei 
crittosistemi. La ricerca di numeri primi e il proble- 
ma della fattorizzazione così come l'analisi del mese 
scorso circa gli algoritmi greedy ci suggeriscono di ap- 
profondire alcuni importanti metodi per la trasmis- 
sione sicura dei dati. Vedremo come una formulazio- 
ne leggermente differente del problema di knapsack 
(il problema del ladro) ci introdurrà una pietra milia- 
re della crittografia a chiave pubblica, ovvero l'algo- 
ritmo di Merkle Hellman. Esploreremo altri metodi 
che afferiscono a tale ambito, alcuni poco conosciuti 
perché poco usati, ma molto interessanti da un pun- 
to di vista procedurale. E altri, già osservati in passa- 
to, come RSA più conosciuti e dalle innumerevoli ap- 
plicazioni pratiche. La discussione non si esaurirà con 
questo articolo. Preannuncio per il prossimo numero 
l'interessante crittografia quantistica, che sta alimen- 
tando in questo periodo, un'intensa discussione. 



MERKLE-HELLMAN 

Si tratta di uno dei primi crittosistemi. È esplicativo 
circa le problematiche e le tecniche per la cifratura, 
anche se non ha prestazioni adeguate che ne possano 
giustificare un effettivo uso nel campo della sicurezza. 
Si tratta di un caso particolare del problema di Kna- 
psack. È basato sulla somma di sottoinsiemi. Dato una 
lista di numeri è un numero z, questi sarà la somma di 
un sotto insieme della lista. In altri termini z si ottiene 



QUANDO UN NUMERO E COPRIMO! 



Due numeri sono coprimi tra di 
loro se non hanno alcun divisore 
comune. O in altri termini se il 
massimo comun divisore tra i due 



numeri è uno. La notazione per 
esprimere questa proprietà tra 
due numeri a e b è quindi: 

MCD(a,b)==1 



come la somma di alcuni dei numeri che compongo- 
no la lista iniziale. Il problema è conosciuto come NP- 
completo. Si distinguono casi "facili" che possono es- 
sere risolti rapidamente. Vi sono però anche casi dif- 
ficili. Si impone così lo schema di Merkle che tenta di 
trasformare casi difficili in facili e viceversa. Passiamo 
alle peculiarità del metodo. Inizialmente si conside- 
ra un insieme crescente di numeri tranne lo zero, ta- 
le che ogni numero sia maggiore della somma dei pre- 
cedenti. 

x=(xl, x2, x3, ... xn) 

Un insieme (sacco) così composto si intende riempi- 
to con crescita esponenziale o (super crescita). Tale 
sequenza ricorda solamente quella di Fibonacci, per 
la quale ogni elemento è la somma dei due prece- 
denti. Un esempio di tale sequenza è {1, 2, 4, 8, 16}. Si 
scelgono: un numero q casuale che sia maggiore o 
uguale della somma dell'insieme dei numeri appena 
indicata, è un numero intero y che sia coprimo con q, 
quindiMCD(y,q)==l. 

La scelta di q assicura l'unicità del messaggio cripta- 
to. y avrà un inverso per permette l'operazione di de- 
crittazione. La chiave pubblica si calcola come una 
sequenza: 

b=(bl, b2, b3, .... bn) 

dove il generico bi = y*xi (mod q). Quindi b è la chia- 
ve pubblica mentre l'insieme (y, x e q) è la chiave pri- 
vata. Vediamo come avvengono le due operazioni di crip- 
tazione e decriptazione. 

Sia a un messaggio: 

a= (al, a2, a3, ... an) 

con ai l'iesimo bit del messaggio. Ovviamente, ai può 
valere o zero o uno. Il messaggio criptato sarà la som- 
matoria di n elementi dei prodotti tra ai e bi. 

c=Si(ai*bi) 



► 110 /Settembre 2006 



http://www.ioprogrammo.it 



Sicurezza dei dati ■ T SOLUZIONI 



In altri termini e è la somma dei valori di b in corri- 
spondenza degli indici i per i quali il messaggio ha bit 
pari a 1 . In tal senso, e per la scelta di q, si comprende 
l'analogia con il problema del ladro come sommato- 
ria di valori. La decrittografia si attua applicando la re- 
lazione inversa. Si calcola il valore s indicato come 
chiave privata. 

s=y"l (mod q) 

La soluzione si può affrontare in modo difficoltoso, si 
parla di complessità NP-hard se l'estrazione di a da e 
si ottiene attraverso uno knapsack riempito in modo 
casuale, mentre di complessità lineare se, come in 
questo caso, il sacco è riempito con la caratteristica 
di crescita esponenziale. Bisogna calcolare ad ogni 
passo della decriptazione c*s (mod q) e x=b*s (mod 
q) . Ricordo che e è il cipher text e a il plain text. Con 
sacco così come lo abbiamo riempito, ossia con la su- 
per crescita è facile (da un punto di vista algebrico) 
pervenire alla soluzione. Si considera il valore più gran- 
de di x, xk. Se xk è maggiore di e allora vorrà dire che il 
corrispondente ak=0 altrimenti se xk è minore di e al- 
lora ak=l. Fine primo passo. A questo punto si scor- 
pora (sottrae) da e il prodotto ak*xk e si ripete l'operazione 
per l'elemento precedente di indice k-1. Si ripete l'o- 
perazione, decrementando k, fin quando non si è com- 
posto completamente a. Quando q è molto grande ri- 
sulta difficoltoso calcolare s. La moltiplicazione modulare 
è il collo di bottiglia che può richiedere molto tempo. 



ve di cifratura e decifratura era identica. Per capire il con- 
cetto di chiave è sufficiente introdurre il più semplice 
degli algoritmi di crittografia, quello per sostituzione. 
Si supponga di avere testo in chiaro "attuare piano 
b" . Al fine di cifrare il testo si può pensare di sostitui- 
re ogni lettera del testo in chiaro con la lettera di due 
successiva secondo l'alfabeto inglese di uso comune. 
Il numero due non è altro che il valore della chiave 
(k=2) . Il cipher text così ottenuto è: "cwwct kn rkcpq d". 
Il metodo esposto ha un valore meramente didattico 
poiché è molto semplice da demolire, ad ogni modi 
ci fa capire il significato di chiave. Quando la chiave è 
identica si parla di metodo a chiave segreta. DES (Da- 
ta encryption standard) sviluppato da IBM è più co- 
nosciuto tra questi. Il problema principale per tali me- 
todi è la necessità di individuare un canale sicuro per 
lo scambio tra mittente e destinatario delle chiavi. È evi- 
dente che non si può trattare dello stesso canale dove 
usualmente avvengono le comunicazione altrimenti 
non si capirebbe l'esigenza di cifrare i dati se questo ve- 
nisse considerato sicuro. L'alternativa sono una serie 
di algoritmi per i quali non è richiesta la presenza di un 
canale sicuro me è sufficiente usare il canale standard 
che verrà usato anche per il setup del metodo. Ap- 
partengono a questa famiglia gli algoritmi a chiave 
pubblica come quello di Merkle-Hellman visto prima. 
Un esempio che introduce "magnificamente" l'ambi- 
to su cui ci muoviamo prevede lo scambio di dati at- 
traverso posta standard tra due individui, Alice e Bob, 
coppia ormai conosciuta dai crittografi visto che è di 
fatto citata in letteratura ogni qual volta si devono fa- 



CIRCA LA CRITTOGRAFIA 
A CHIAVE PUBBLICA 

Un breve cenno per chi legge per la prima volta di crit- 
tografia. Sarà noto che si tratta dei metodi che vengo- 
no usati nel campo della sicurezza informatica. Ogni 
qual volta vogliamo inviare dati che desideriamo man- 
tenere riservati, o semplicemente quando si intende 
archiviare dei dati in modo che eventuali occhi indiscreti 
non possano comprenderli si fa uso di metodi di crit- 
tografia. A dire il vero esiste anche un'altra grande fa- 
miglia di metodi che afferisce alla steganografia che 
ha il compito di "nascondere" le informazioni all'interno 
di altre informazioni di uso comune, come ad esem- 
pio la foto digitalizzata della nostra prima comunione. 
Ma questo è un capitolo che abbiamo già affrontato e 
che ci proponiamo in futuro di riaprire (ioProgram- 
mo n. 71 - Fabio Grimaldi -) . La crittografia semplice- 
mente prende un testo in chiaro conosciuto come 
plain text, applica un algoritmo di crittografia con una 
chiave k e produce un testo cifrato o cipher text. Il te- 
sto può essere così inviato al destinatario o semplice- 
mente può essere archiviato. A destinazione per otte- 
nere il testo in chiaro sarà necessario applicare un al- 
goritmo "inverso" di decrittografia che genera nuova- 
mente il plain text. Nei primi metodi introdotti la chia- 



ALGORITMO DEL PUZZLE 



L' algoritmo del puzzle è un 
algoritmo di crittografia a 
chiave pubblica istruttivo 
poiché contiene molte delle 
idea alla base di tutti gli 
algoritmi asimmetrici ma che è 
difficilmente realizzabile. Fu 
Merkle a introdurlo nel 1974. La 
supposizione iniziale è sempre 
identica: Bob e Alice vogliano 
comunicare in modo sicuro, al 
riparo di Eva che avendo 
accesso al canale di 
comunicazione potrebbe 
intercettare scambi di 
informazione. Bob e Alice 
devono scambiarsi la chiave, è 
non avendo un canale sicuro 
devono usare quello a 
disposizione. Bob crea dei 
puzzle, ovvero tanti messaggi 
codificati con un algoritmo 
facile da forzare. Per puzzle 
nell'ambito proposto da Merkle 
si intende un messaggio cifrato 
abbastanza facile da risolvere 



come abbastanza facile forzare. 
Alice riceve questi puzzle, in 
numero molto elevato 
dell'ordine del milione, e ne 
sceglie uno a caso. Lo risolve, 
ovvero forza la cifratura. A 
questo punto Alice legge il 
messaggio contenuto nel puzzle 
che dice qualcosa del genere: 
"Sono il puzzle numero x, la 
chiave numero x è y". A questo 
punto Alice comunica a Bob il 
numero del puzzle: x. In questo 
modo Alice e Bob hanno una 
chiave in comune: y. Anche può 
conoscere la chiave y, avendo 
intercettato lo scambio dei 
puzzle, ma è mischiata tra un 
milione di altre chiavi. A questo 
punto potrebbe provare a 
risolvere tutti i puzzle fino a 
trovare il puzzle numero x, ma 
il numero dei puzzle è scelto in 
modo che questa operazione sia 
computazionalmente troppo 
lunga. 



http://www.ioprogrammo.it 



Settembre 2006/ ili »> 



SOLUZIONI T ■ Sicurezza dei dati 




re esempi, e noi non siamo da meno! Come prima 
azione Alice mette nella cassetta il messaggio, la chiu- 
de con il suo lucchetto mediante chiave KA e la spedisce 
a Bob. Questi riceverà la cassetta applicherà il suo luc- 
chetto con chiave KB e rispedirà la cassetta con i due 
lucchetti nuovamente ad Alice. Alice toglierà il suo 
lucchetto (visto che è in possesso della chiave B) e spe- 
dirà per l'ultima volta la cassetta a Bob, il quale non 
dovrà fare altro che aprire la cassetta con la sua chia- 
ve KB. Questo è solo un protocollo per sfruttare il ca- 
nale pubblico, gli algoritmi di crittografica, nella nostra 
metafora sono i lucchetti. Ovviamente, la rivoluzione 
sta nell'aver comunicato segretamente avendo usato 
un canale pubblico, quindi per definizione insicuro. Un 
modo analogo per specificare lo stesso concetto è il 
seguente esempio: i lucchetti rappresentano le chia- 
vi pubbliche e le chiavi le chiavi private (scusate la ca- 
cofonia). Alice chiede a Bob di spedirle il suo lucchet- 
to, già aperto. La chiave dello stesso verrà custodita 
da Bob. Alice riceve il lucchetto e, con esso, chiude il la 
cassetta con il messaggio e la spedisce a Bob. Questi ri- 
ceve il pacco e può aprirlo con la chiave di cui è unico 
proprietario. 



L'ALGORITMO RSA 

Il più conosciuto dei metodi di crittografia a chiave 
pubblica è opera di R. Rivest, A Shamir e L. Adleman, 
le cui iniziali hanno dato nome al metodo. Il tutto si 
basa su una funzione matematica la cui espressione al- 
gebrica è molto semplice. Come vedremo risulterà 
molto complessa la trattazione numerica. In associa- 
zione ad una funzione simile per la decrittazione, de- 
finisce i due algoritmi distinti di crittografia e di de- 
crittografia. Siano E C, e, d e n dei numeri e valga la 
seguente relazione: 



C = P e mod n 



(1) 



Che verrà adottata, per la crittazione. 
Allora esisterà un numero d tale che: 



P = C d mod n 



(2) 



Funzione di decrittazione. Più avanti capiremo il si- 
gnificato delle diverse variabili. Sfruttando la proprietà 
di simmetria della funzione modulo si nota che le due 
funzioni di crittazione e decrittazione sono l'una l'in- 
versa dell'altra e vale la proprietà commutativa. 

P = C d mod n = C = (P e ) d mod n = (P d ) e mod n 

A questo punto si supponga che P sia il plaintext o 
blocchi appartenenti ad esso di lunghezza massima 
n. C sia il ciphertext o blocchi di esso; e e d siano del- 
le variabili che come vedremo dovranno essere mol- 
to grandi. L'algoritmo RSA funziona come esposto 



nei passi che illustriamo di seguito: 

1. Si considerano due numeri primi qualsiasi p e q 
molto grandi dell 'ordine di 1 01 00. 

2. Si determina il prodotto n=pq. 

3. Si determina prodotto m=(p-l)(q-l) 

4. Si calcola un numero d che sia minore di m ma che 
sia rispetto a m un numero primo, dedm non han- 
no fattori primi in comune, d è dispari mentre m è 
pari. 

5. Una volta scelto d, si determina un numero e che sod- 
disfi l'equazione: 

ed = 1 (mod m) 

Ovvero e dovrà essere l'inverso di d modulo m. 

La soluzione dell'equazione per determinare e, come 
detto prima, non è affatto semplice da un punto di vi- 
sta numerico, soprattutto non lo è nel campo degli in- 
teri modulo z, dove z può assumere un qualsivoglia 
valore intero. Esistono comunque dei teoremi dell'al- 
gebra che ne danno una giustificazione matematica. 
Quindi, per cifrare si usa la relazione 1 da cui si ottie- 
ne il ciphertext C e per decifrare la 2 da cui si ottiene il 
plaintext P. Per cifrare bisogna conoscere la coppia di 
numeri e, n, mentre per fare l'operazione inversa de- 
vono essere noti d, n. Considerato che n è nota, l'idea 
rivoluzionaria sta nel rendere pubblica, quindi nota, 
anche e, ossia la chiave per cifrare, mentre rimarrà se- 
greta d. La difficoltà è insita nell'operazione di scom- 
posizione in fattori di n che è un numero grandissi- 
mo. Se si riuscisse ad analizzare la fattorizzazione di n 
si potrebbero individuare i due numeri p e q e conse- 
guentemente m e quindi essendo noto e anche d; ma 
come detto tale operazione è talmente complessa da 
poterla definire "oggi" quasi impossibile. I calcoli di 
Rivest dicono che la fattorizzazione di un numero con 
500 cifre richiederebbe 10 A 25 anni!! In definitiva vi so- 
no due chiavi, una del trasmettitore che deve essere 
privata e che nel caso specifico è d, mentre è pubbli- 
ca la chiave e (in alcuni casi si considera pubblica la 
coppia e, n) appartenente al destinatario. In definiti- 
va Alice rende pubbliche le sue chiavi, la coppia (e,n) 
cosicché se qualcuno vuole inviarle un messaggio lo ci- 
frerà mediante la relazione 1, supponiamo che a far- 
lo sia Bob. Una volta che Alice riceverà il messaggio, 
con la sua coppia di chiavi private otterrà il plain text. 
A scopo puramente didattico facciamo un esempio 
sull'uso del metodo RSA. Per fare una prova, per sem- 
plicità di calcolo non considereremo chiavi che ri- 
spetteranno le specifiche del metodo, ovvero che sia- 
no dell'ordine di 10 A ^"^, ma saranno numeri molto 
piccoli, per poter fare i conti con maggiore agio. Ad 
ogni modo vedremo come anche così si presentano 
problemi. Ho fatto qualche prova che mi consentisse 
di individuare numeri "giusti". Ho preso p=5 e q=17che 
sono due numeri primi. 
n=pq=85 mentre m=(p-l)(q-l)=64 
Se si pone d=13 (questa è la chiave segreta non ditela 



► 112 /Settembre 2006 



http://www.ioprogrammo.it 



Sicurezza dei dati ■ T SOLUZIONI 



in giro) si ottiene dalla relazione ed=l (mod 64) un va- 
lore di e pari a 5, provare per credere! Dovremo adot- 
tare un alfabeto di cardinalità n=45. Con i numeri scel- 
ti P non verrà associato a blocchi di caratteri ma ad 
un solo carattere. Supponiamo che la a sia codificata 
con il numero 1 la b con il numero 2 e così via e che il 
messaggio da cifrare sia "eia" (in tema di sicurezza mi 
sembra una scelta azzeccata!) . La crittazione si otterrà 
applicando la relazione 1. AP corrisponde il codice del- 
la 'e' ovvero 3. Applicando la formula si ottiene C=73. 
Così per le altre due lettere 'i' e 'a' il codice crittografato 
varrà rispettivamente 59 e 1. Se si prova a decrittare 
si deve usare la formula 2. Per la lettera 'e' il cui codi- 
ce crittografato vale 73 la potenza C Ac * vale 
47477585226700098686074966922953 cifra più cifra 
meno (scherzo il calcolo è esatto) il cui modulo di n è 
proprio 73. 



BLUM GOLDWASSER 

Un altro interessante algoritmo di crittografia asim- 
metrica, per molti versi simile a RSA è quello di Blum 
Goldwasser, introdotto nel 1984. È classificato come al- 
goritmo probabilistico semanticamente sicuro. La di- 
mensione del cipher text aumenta di un modo linea- 
re rispetto alla dimensione del plain text. Alla base del- 
l'algoritmo c'è la generazione di una sequenza di nu- 
meri pseudo casuali attraverso l'algoritmo Blum Blum 
Shub (BBS). Come per RSA la sicurezza è legata alla 
"intrattabilità" del problema di fattorizzazione di nu- 
meri interi. Qualora si consideri un numero n come 
il prodotto p*q di due numeri primi molto grandi. Qui 
la sicurezza del metodo è basata soltanto sulla diffi- 
coltà insita nella fattorizzazione e non in altre specifi- 
che come il residuo quadratico oppure assunzioni 
matematiche come per RSA. Anche la quantità di spa- 
zio occupata è un vantaggio visto che è proporziona- 
le al plain text. Poiché per criptare si usa un algoritmo 
probabilistico uno stesso testo in chiaro può produr- 



re in distinte applicazioni diversi testi criptati; è que- 
sta è un'ulteriore vantaggio del metodo. Purtroppo ha 
risultati pessimi ad attacchi conosciuti come "chosen 
cipher text" Entriamo nei particolari. Serviamoci sem- 
pre dei nostri amici Alice e Bob. 

1. Generazione delle chiavi. Alice individua due nu- 
meri primi p e q molto grandi tali che entrambi sia- 
no congruenti a 3 modulo 4. Ciò significa che di- 
visi per 4 danno resto 3. Successivamente, si cal- 
cola l'intero di Blum N=p*q. Così, la chiave pub- 
blica è N mentre la chiave privata è la sua fattoriz- 
zazione p*q. 

2. Criptazione del messaggio. Bob esprime il mes- 
saggio m come la sequenza di L bit (mO, mi, m2, 
. . . m^. ]) . Poi sceglie un elemento casuale y com- 
preso tra 1 e N e calcola xq= y^ mod N A questo 
punto Bob usa il generatore di numeri casuali co- 
me segue: con seme s vengono generati L bit ca- 
suali (bO, bl, b2, .. b^i) che saranno la chiave: 



x 0= 


S 2 








for 


= to L-l do 








bi è 


il bit meno sig 


nificativo 


d 


xi 


Calcola Xj=(Xj_i)2 


mod N 







Poi Bob produce il cipher text come XOR tra i bit 
di m con quelli della chiave b. 



c=b xor m 
z=xq2 l mod N 



■ c L-l) ■ 



quindi invia la sequenza e (cO, ci, c2 . 
3. Decrittografia 

Alice riceve (cO, ci, c2 ... cL-l) ez. Può ripristinare 
m usando la procedura seguente: 
Mediante i fattori primi (p,q), Alice calcola 
y p =z«P +1 ) /4 ) L mod p e y p =z«<?+l) /4) L mod q 
Calcola il seme iniziale usato dal BBS 

x =q(q" 1 mod p)y p +p(p _1 mod q) y p mod N 




XOR 

Si tratta di un 
operatore logico 
simile all'OR la cui 
tabella di verità è la 
seguente c=a xor b 



f 

a 


b 


e 














1 


1 


1 





1 


1 


1 






CHOSEN CHIPER TEXT 



Si tratta di uno dei 
modelli d'attacco per 
criptare un messaggio 
cifrato. Il crittanalista 
sceglie un cipher text 
(da qui il nome del 
metodo) e prova a 
decriptare con chiavi 
non conosciute. 
Ovviamente, per 
portare a termine 
l'attacco è necessario 
del tempo (la quantità 
determina la bontà del 
metodo di crittografia 



o la fortuna 
dell'attaccante); 
normalmente tanto 
tempo. Spesso si 
usano delle macchine 
(computer) per tentare 
tutte le combinazioni 
possibili di chiavi nel 
minor tempo 
possibile. Per alcuni 
algoritmi questo 
attacco non sortisce 
nella stragrande 
maggioranza dei casi 
alcun risultato. 



Da xg, calcola il vettore di bit b usando il generato- 
re BBS, come nell'algoritmo di crittazione. 
Calcola il testo originale mediante XOR della chia- 
ve con il testo criptato: m=c xor b. 
Alice ha ottenuto così il messaggio m. 



CONCLUSIONI 

Continueremo ad esplorare il mondo della crittogra- 
fia. In particolare nel prossimo numero analizzeremo 
ai raggi x un metodo che in questo periodo ha susci- 
tato un particolare interesse, si tratta della crittografia 
quantistica. 

Fabio Grimaldi 



http://www.ioprogrammo.it 



Settembre 2006/ 113 ►