Tesi Todone

110
Università Degli Studi di Trieste Facoltà di Ingegneria Corso di Laurea Specialistica in Ingegneria Informatica Tesi di laurea in reti di calcolatori Progetto e realizzazione di una infrastruttura modulare per acquisizione ed archiviazione remota di documenti LAUREANDO RELATORE Giancarlo Todone Prof. Alberto Bartoli CORRELATORE Ing. Giorgio Davanzo Anno Accademico 2008/2009

description

Tesi di laurea di Giancarlo Todone dal titolo "Progetto e realizzazione di una infrastruttura modulare per acquisizione ed archiviazione remota di documenti"

Transcript of Tesi Todone

Page 1: Tesi Todone

Università Degli Studi di TriesteFacoltà di Ingegneria

Corso di Laurea Specialistica in Ingegneria Informatica

Tesi di laurea in reti di calcolatori

Progetto e realizzazione di una infrastrutturamodulare per acquisizione ed archiviazione

remota di documenti

LAUREANDO RELATORE

Giancarlo Todone Prof. Alberto Bartoli

CORRELATORE

Ing. Giorgio Davanzo

Anno Accademico 2008/2009

Page 2: Tesi Todone
Page 3: Tesi Todone

Talk is cheap. Show me the code!(Linus Torvalds)

Page 4: Tesi Todone
Page 5: Tesi Todone

Indice

1 Introduzione 1

2 Il caso di studio 32.1 Situazione iniziale e requisiti . . . . . . . . . . . . . . . . . 32.2 Architettura generale e definizioni . . . . . . . . . . . . . . 5

2.2.1 Flusso di un tipico caso di utilizzo . . . . . . . . . 92.3 Cenni di implementazione e tecnologie utilizzate . . . . . . 11

3 SyncUtils 133.1 Requisiti e scopi di SyncUtils . . . . . . . . . . . . . . . . 133.2 Architettura . . . . . . . . . . . . . . . . . . . . . . . . . . 143.3 Dettagli implementativi e tecnologie . . . . . . . . . . . . 20

3.3.1 Perché il file system? . . . . . . . . . . . . . . . . . 203.3.2 Meccanismo di sincronizzazione . . . . . . . . . . . 213.3.3 Identificativi di richieste e risposte . . . . . . . . . 233.3.4 Protocollo . . . . . . . . . . . . . . . . . . . . . . . 243.3.5 Problematiche delle notifiche . . . . . . . . . . . . 273.3.6 Formati dei file di comunicazione . . . . . . . . . . 283.3.7 Serializzazione XML . . . . . . . . . . . . . . . . . 323.3.8 COM . . . . . . . . . . . . . . . . . . . . . . . . . 35

3.4 Installazione e preparazione dell’ambiente di esecuzione . . 40

i

Page 6: Tesi Todone

ii INDICE

4 GEC_Scan 434.1 Requisiti e progetto dell’interfaccia utente . . . . . . . . . 43

4.1.1 Interfaccia grafica e usabilità . . . . . . . . . . . . 444.2 Composizione di GEC_Scan . . . . . . . . . . . . . . . . . 49

4.2.1 TWAIN . . . . . . . . . . . . . . . . . . . . . . . . 504.2.2 VisualSlideShow e design delle classi coinvolte . . . 55

4.3 Tecnologie e tecniche implementative . . . . . . . . . . . . 584.3.1 dotNetTwain . . . . . . . . . . . . . . . . . . . . . 594.3.2 Grafica . . . . . . . . . . . . . . . . . . . . . . . . 68

4.4 Installazione e preparazione dell’ambiente di esecuzione . . 70

5 Sottosistema di archiviazione e plug in 735.1 Caratteristiche del sottosistema di archiviazione . . . . . . 73

5.1.1 Funzionalità di manipolazione file . . . . . . . . . . 755.2 Design del sottosistema di archiviazione . . . . . . . . . . 765.3 Specifiche e tecnologie . . . . . . . . . . . . . . . . . . . . 80

5.3.1 Archiviazione locale e debug . . . . . . . . . . . . . 845.3.2 Funzionalità estese ed archiviazione Remota . . . . 85

5.3.2.1 Sharepoint . . . . . . . . . . . . . . . . . 865.3.2.2 Google Documents . . . . . . . . . . . . . 92

5.4 Setup dei sistemi di archiviazione . . . . . . . . . . . . . . 97

6 Conclusioni 99

Bibliografia 103

Page 7: Tesi Todone

Capitolo 1Introduzione

La gestione di un documento cartaceo per via informatica inizia con leoperazioni di acquisizione ed archiviazione. Per “acquisizione” si intendel’operazione di traduzione e codifica di un documento cartaceo in unaforma comprensibile e fruibile da un elaboratore. Per “archiviazione” sipuò distinguere tra la mera operazione di immagazzinamento dati e la“conservazione sostitutiva”—con la quale si intende tutto il complessodi azioni che permettono di conservare elettronicamente dati di valorelegale o tributario senza per questo conservare anche i documenti cartaceioriginali.

A seguito e come proseguimento del tirocinio svolto presso la soft-ware house MIDA4, lo scrivente ha realizzato un pacchetto software perconsentire di aggiungere le funzionalità di archiviazione al software dicontabilità preesistente GEC. Tale pacchetto fornisce una infrastrutturaper interfacciare GEC con altri sistemi di archiviazione (già esistenti ofuturi) grazie ad un sistema estendibile con plug in, e si inserisce in unpiù ampio contesto di gestione documentale in sviluppo nel “Laborato-rio Reti” del DEEI, Università Degli Studi di Trieste. Un tema trattatocon particolare riguardo è quello dell’archiviazione remota, cioè l’inte-grazione con servizi di terze parti—come Google Documents o MicrosoftSharepoint—per la memorizzazione dei dati su un server connesso adInternet.

1

Page 8: Tesi Todone

2 1. Introduzione

Dall’osservazione della situazione di partenza, dopo lo studio del pro-blema nella sua accezione più generale, sono stati definiti dei requisitiche hanno portato alla suddivisione del lavoro nei tre moduli softwareresponsabili di comunicazione, acquisizione e archiviazione; per ognunodei tre moduli sono stati definiti ulteriori requisiti in base ai quali sonostate poi concepite l’architettura e le specifiche tecnologiche di ogni sin-gola parte. Ogni classe o componente sviluppato è stato verificato conmetodologie di unit-test ed in alcuni casi anche con test automatici dicarico. L’intero progetto ha subito anche diversi test funzionali condottida operatori umani.

I requisiti tecnologici del committente hanno portato alla scelta dellinguaggio C# e del framework dotNet all’interno dell’ambiente di svi-luppo integrato Visual Studio 2008, su un sistema operativo WindowsXP/Vista. L’interfacciamento con le periferiche di acquisizione è gestitocon lo standard TWAIN mentre l’interfacciamento con il software GECè gestito con le tecnologie COM e XML.

Nel capitolo 2 si affrontano tematiche di carattere generale inerentil’insieme del software sviluppato. Nei tre capitoli successivi ( 3 nella pa-gina 13, 4 nella pagina 43, 5 nella pagina 73) si affrontano separatamentei tre moduli software, esponendo di ognuno:

• situazione pregressa e/o requisiti;

• architettura e definizioni;

• tecniche implementative e tecnologie utilizzate;

aggiungendo—ove pertinente—un breve riassunto delle operazioninecessarie all’installazione e alla manutenzione del modulo.

Page 9: Tesi Todone

Capitolo 2Il caso di studio

2.1 Situazione iniziale e requisiti

La software house MIDA4 ha prodotto e mantiene il software di con-tabilità chiamato GEC. La necessità dei clienti di MIDA4 di archiviaredocumenti per via informatica contestualizzandoli con le loro situazioniamministrative e altri dati, ha spinto la software house a ricercare unmodo per ampliare in tal senso le capacità del suo prodotto.

La richiesta era quella di aggiungere le funzionalità desiderate in unmodo che permettesse di iniziare a servirsi di tecnologie più recenti epromettenti senza per questo dover riscrivere da capo un programma giàrodato e funzionante come GEC.

GEC viene attualmente fornito in due versioni: installabile e ASP(2.2):

• la versione installabile è un normale programma che risiede ed ope-ra sul personal computer dell’utente finale, ed eventualmente co-munica con un server centralizzato per recuperare informazioni dilicenza ed aggiornamenti;

• la versione ASP consiste nella versione installabile montata però suun server accessibile da molti fruitori contemporaneamente tramiteInternet ed un software di remote desktop.

3

Page 10: Tesi Todone

4 2. Il caso di studio

Il software necessario ad aggiungere le funzionalità di archiviazione de-siderate, deve necessariamente interagire con GEC—qualsiasi sia la suaubicazione—ma deve anche interagire con l’hardware dell’utente fina-le (es: scanner e fotocamere) e deve essere in grado di comunicareautonomamente con eventuali servizi di archiviazione di terze parti.

Il modo in cui il nuovo software si integra con GEC deve

1. richiedere il minimo sforzo in termini di modifiche al codicesorgente di GEC;

2. essere facilmente utilizzabile dagli sviluppatori di GEC;

3. permettere l’integrazione futura con nuovi servizi di terze partisenza riscrivere il codice sorgente;

per poter permettere rispettivamente:

1. di rendere il più possibile indipendenti lo sviluppo e il manteni-mento di GEC da quelli del nuovo software di archiviazione;

2. di consentire una rapida integrazione al momento del rilascio;

3. di poter essere rapidamente espandibile con nuove funzionalità.

Dal punto di vista dell’utente, il software sviluppato dev’essere:

• facilmente integrabile con il proprio sistema di produzione;

• di utilizzo semplice ed immediato.

In quest’ottica, un sistema di astrazione delle periferiche di acquisi-zione immagini dell’utente è stato posto come requisito; fondamentale èanche la trasparenza di tale meccanismo, necessaria al fine di ottenereun’interfaccia grafica consistente per tutti gli utenti, a prescindere damarca e modello dei loro hardware.

Infine, la scelta dell’ambiente di sviluppo ha dovuto tenere conto divarie richieste:

• GEC opera in ambiente Microsoft Windows, e quindi anche il nuovosoftware di archiviazione deve funzionare almeno in tale sistema;

Page 11: Tesi Todone

Architettura generale e definizioni 5

• esso deve consentire di proporre all’utente finale un’interfacciapiacevole, immediata e consistente;

• metodologie, linguaggi, librerie, framework utilizzati (a parte quellifinora citati che hanno diverse motivazioni) devono essere allo statodell’arte, o quantomeno ancora vivamente supportati da produttorie da una nutrita schiera di sviluppatori; essi devono però permet-tere allo sviluppatore di interfacciarsi anche con moduli softwareutilizzanti tecnologie meno recenti, come TWAIN o Visual Basic 6(di cui—come vedremo—fanno uso alcune parti del sistema).

Da ciò si evince come la capacità di interoperabilità tra diverse tecnolo-gie sia essa stessa un requisito; viste queste necessità, in fase di analisipreliminare è stato posto l’utilizzo del dotNet framework di Microsoftcome requisito.

2.2 Architettura generale e definizioni

Per motivi di natura tecnica e per questioni di manutenibilità del codiceche vedremo in seguito, il modulo che dovrà svolgere le operazioni diacquisizione e archiviazione dev’essere indipendente, cioè non fare partedi GEC, ma essere compilato in un eseguibile autonomo: questo significache GEC e il nuovo software di acquisizione sono due entità distinte chenecessitano di comunicare.

Si considerino quindi i seguenti attori:

GEC è il programma di contabilità già esistente, che dovrà subire dellemodifiche per poter utilizzare SyncUtils e comunicare con il soft-ware di nuova creazione dedicato all’acquisizione e archiviazione;in seguito, se non esplicitamente specificato, col nome di GEC cisi riferirà indistintamente al programma in versione tradizionale oASP;

GEC_Scan è il software di acquisizione e archiviazione: esso è un soft-ware a se stante, ma può dialogare con GEC—tramite un mec-canismo descritto in 3.3 nella pagina 20—e con servizi di terzeparti—mediante dei moduli aggiuntivi chiamati plug in ( 5.3 nellapagina 80).

Page 12: Tesi Todone

6 2. Il caso di studio

GEC-1 ASP

User 2

User 1

User 3

GEC-2

GEC-3

GEC_Scan

GEC_Scan

GEC_Scan

ASP

Rem

ote

desk

top

ASP

Rem

ote

desk

top

����

����

����

����

����

����

����

����

����

����

����

����

����

����

����

����

����

Inte

rnet

(B)

(C)

(A)

Figura 2.1: Tre casi di utilizzo del sistema di archiviazione: nel caso (A)l’utente 1 utilizza solo l’istanza 1 di GEC tramite ASP e il suo sistema di

remote desktop; nel caso (C) l’utente 3 utilizza solo GEC-3 in esecuzione sul

suo computer locale; nel caso (B), l’utente 2 utilizza sia la locale istanza 2 di

GEC, sia GEC-1 tramite sistema ASP.

Queste due entità devono poter comunicare tra loro in vario modo.Nel caso più semplice GEC e GEC_Scan vengono eseguiti sullo stessocalcolatore e comunicano senza interferenze esterne; in figura 2.1 si os-servano anche i casi in cui GEC sia remoto e quello più complesso in cui

Page 13: Tesi Todone

Architettura generale e definizioni 7

un solo utente utilizzi più istanze di GEC, eventualmente miste tra localie remote.

GEC

Sync

Utils

GEC_Scan

plug in

plug in

plug in

softwarepreesistente

comunicazioni

funzionalità

acquisizione

archiviazione

softwarenuovo

Figura 2.2: Descrizione dei software coinvolti; GEC è preesistente e viene

modificato solo per poter usare SyncUtils; il resto del software è sviluppato

ex novo; di questo è visibile la suddivisione in comunicazioni, acquisizione ed

archiviazione: solo le ultime due implementano funzionalità richieste, mentre

la prima serve a rendere interoperabili nuovo e vecchio software.

Come illustrato in figura 2.2, tutte le funzionalità aggiunte risiedonoin GEC_Scan e nei suoi plug in, mentre la libreria SyncUtils consente aGEC di comunicare con GEC_Scan e di utilizzare tali funzionalità.

Si consideri inoltre la seguente nomenclatura:

Utente è l’utente finale di GEC e di GEC_Scan, colui che opera i pro-grammi per archiviare documenti; si faccia attenzione alla differen-za tra “utente finale” e l’utente di una libreria (sviluppatore) o diun servizio (potrebbe essere un modulo software);

Page 14: Tesi Todone

8 2. Il caso di studio

Documento un insieme di più immagini corredate da meta dati;

ASP acronimo di Application Service Provider, è il sistema che permet-te tramite un remote desktop di utilizzare dal PC dell’utente finaleun’istanza di GEC in esecuzione su un server remoto; da non con-fondersi con Active Server Pages di Microsoft (di cui non si parlamai in questo testo);

Plug in è un modulo software che consente di aggiungere funzionalitàa GEC_Scan senza la necessità di modificare o ricompilare il suocodice sorgente;

Servizio esterno un qualsiasi servizio di archiviazione di documentiestraneo sia a GEC che a GEC_Scan, probabilmente pubblicatotramite un servizio web.

Sessione di acquisizione l’insieme di operazioni iniziate dall’utenteche portano all’acquisizione, riorganizzazione in documenti e archi-viazione di un insieme di immagini con i loro meta dati associati(punti da 2 a 9 in 2.2.1 nella pagina 10 e figura 2.3; si noti che tra ilpunto 3 e il punto 4 il sistema rimane indefinitamente in attesa diistruzioni dall’utente; quindi può essere un operazione che richiedemolto tempo).

In aggiunta—se non per esigenze particolari—si eviterà di seguito l’uti-lizzo di termini come “server” e “client” per riferirsi a GEC o GEC_Scan,poiché potrebbero essere causa di fraintendimenti; infatti nella sua ver-sione ASP, il software GEC viene eseguito su una macchina che interpretail ruolo di server, ma per correttezza dovrebbe essere considerato clientdel software di acquisizione che gli offre per l’appunto un servizio.

Page 15: Tesi Todone

Architettura generale e definizioni 9

2.2.1 Flusso di un tipico caso di utilizzo

(A):

GE

C

(C):

GE

C_

SCA

N

Ute

nte

(D):

Plu

gin

(E):

Serv

izio

este

rno

(B):

Sync

Utils

1.richiede iniziosessione di acquisizione

2.Request

9.Response

3.mostra formprincipale

4.accetta oannulla

5.esegue ilplug in adeguato

8.fine del job

6.sottomettedocumenti

7.fine del job

tem

po\\

Acquisizione(tempoindefinito)

������������������������������������������������������������������������ ����������������������������������������������������������������������������

Figura 2.3: Flusso di esecuzione di una richiesta e relativa risposta; vede-

re 2.2.1 nella pagina successiva per una descrizione puntuale dei passi nume-

rati; la progettazione e creazione delle entità marcate come (B), (C) e (D)costituiscono il caso di studio; le linee ondulate indicano il punto in cui l’utente

può causare un’attesa a tempo indeterminato del sistema; (B) risolve i proble-

mi di comunicazione tra (A) e (C) siano essi sulla stessa macchina oppure su

macchine diverse comunicanti tramite Internet.

Page 16: Tesi Todone

10 2. Il caso di studio

Un tipico caso di utilizzo del sistema—nel quale una singola istanza diGEC comunica con una singola istanza di GEC_Scan—si svolge co-me di seguito (i punti numerati si riferiscono a figura 2.3 nella paginaprecedente):

• il sistema dell’utente si avvia; parte automaticamente anche il soft-ware di acquisizione e carica dalla cartella plugins le estensionidi cui è stato dotato;

• l’utente carica e opera GEC (versione installabile o ASP), mentreil programma di acquisizione (eseguito allo start up sul sistemadell’utente) resta in attesa nascosto;

1. l’utente esegue un’operazione su GEC per la quale è previstal’acquisizione di un certo numero di documenti;

2. GEC—tramite una chiamata all’apposita libreria di comunicazioneSyncUtils—effettua una richiesta a GEC_Scan; ad esso (sia que-sto in esecuzione sulla medesima macchina o su di una diversa)viene segnalato di mostrare la sua finestra principale, inviandoglinel contempo i meta dati da associare ai documenti che si andràad acquisire ed una lista di azioni desiderate da intraprendere sudi essi; se la finestra era già aperta a seguito di una precedenterichiesta non ancora soddisfatta, il lavoro viene messo in coda;

3. GEC_Scan accetta la richiesta e la accoda ad una lista o la scartarispondendo con una lista di errori (ad esempio quando non è ingrado di gestire la richiesta);

4. l’utente usa le funzionalità del programma di acquisizione per scan-sionare1 ed ordinare un certo numero di pagine inerenti la richiestaaccettata; l’utente può inserire dei separatori tra gruppi di immagi-ni per organizzare il materiale acquisito in documenti: ad ogni do-cumento vengono associati tutti i meta dati ricevuti; alla fine dellariorganizzazione e separazione dei documenti, l’utente sottomettei dati o annulla la sessione con appositi comandi;

1Sulla scelta tra gli equivalenti italiani dell’inglese “to scan” l’Accademia dellaCrusca si è espressa nelle “Risposte ai quesiti” concludendo che sono accettabili tuttele soluzioni (scandire, scannare, scannerare, scannerizzare, scansionare) [3].

Page 17: Tesi Todone

Cenni di implementazione e tecnologie utilizzate 11

5. GEC_Scan cerca tra i plug in caricati quelli in grado di soddisfarele richieste effettuate da GEC tramite la libreria di comunicazioneed esegue ogni operazione ritenuta pertinente su ogni documento;

6. questo può comportare il dialogo con un ulteriore software di ar-chiviazione, anche residente su una macchina diversa da quella sucui è in esecuzione GEC e da quella su cui esegue il programmadi acquisizione (esempio: inviare tutti i documenti ad un servizioweb);

7. il software di acquisizione completa ogni elaborazione e compila unrapporto con il dettaglio delle operazioni effettuate e un’eventualelista di errori;

8. il software di acquisizione invia la risposta così costruita a GECsempre tramite libreria di comunicazione;

9. GEC riceve la notifica che i suoi lavori richiesti sono staticompletati (o annullati);

• nel caso la coda di lavori del software di acquisizione non sia vuo-ta, l’utente viene invitato a continuare il suo lavoro con un’altrasessione di sottomissione documenti.

2.3 Cenni di implementazione e tecnologieutilizzate

Il programma preesistente GEC è stato sviluppato in Visual Basic 6,kit di sviluppo capace di generare file di codice eseguibile nativo; essopermette anche una buona interazione con componenti COM.

Nei seguenti tre capitoli, viene trattato il software sviluppato ex novoper aggiungere a GEC le funzionalità di acquisizione e archiviazione:

libreria di comunicazione (progetto di nome “SyncUtils”) che per-mette ad un’istanza di GEC di effettuare richieste ad un’istanza diGEC_Scan e riceverne risposta, in 3 nella pagina 13;

Page 18: Tesi Todone

12 2. Il caso di studio

software GEC_Scan che tramite interfaccia grafica permette l’acqui-sizione di documenti, in 4 nella pagina 43;

plug in che permettono a GEC_Scan di accedere a servizi diarchiviazione di terze parti, in 5 nella pagina 73.

Tutti questi moduli software sono stati sviluppati nel linguaggio C# eutilizzano quindi il dotNet framework (versione 2.0 o successive).

Con riguardo alla libreria di comunicazione, in 3.3.8 nella pagina 35si parla della necessaria metodologia di interazione tra codice mana-ged e codice nativo: l’utilizzo di oggetti dotNet come componenti COMtramite software wrapper.

Quest’ultimo sistema è stato adottato per permettere a GEC di chia-mare delle funzioni sviluppate con tecnologia dotNet; in questo modo lalibreria SyncUtils è richiamabile sia da codice nativo (come avviene perGEC) sia da codice dotNet.

Le funzioni di comunicazione utilizzano un meccanismo di sincronia ecomunicazione basato sulla condivisione di un file system ( 3.2 nella pa-gina 14) per scambiarsi messaggi XML (formato descritto in 3.3.6 nellapagina 28) secondo il protocollo descritto in 3.3.4 nella pagina 24. La ge-nerazione del codice XML avviene tramite meccanismo semi automaticoper serializzazione di oggetti ( 3.3.7 nella pagina 32).

Per l’interfacciamento di GEC_Scan con le periferiche di acquisizio-ne immagini è stato usato TWAIN ( 4.2.1 nella pagina 50)—secondole specifiche versione 1.9 [5]—tramite l’apposito sviluppo della libreriadotNetTwain. TWAIN si presenta come una DLL contenente codicenativo a 32 bit; per l’utilizzo da parte di dotNet, è quindi necessa-rio adottare ulteriori tecniche di interoperabilità con l’aiuto del packageSystem.Runtime.InteropServices ( 4.3.1 nella pagina 59).

Ogni plug in è stato sviluppato come una classe dotNet residentein un assembly dotNet2. Per permettere il rapido sviluppo di plug insono state sfruttate alcune caratteristiche del framework dotNet comereflection e caricamento dinamico di classi.

2Un assembly dotNet è una DLL contenente bytecode dotNet nella forma di unao più classi appartenenti anche a diversi namespace, con i rispettivi meta dati dicontorno.

Page 19: Tesi Todone

Capitolo 3SyncUtils

3.1 Requisiti e scopi di SyncUtils

La parte del progetto che deve interagire più intimamente con GEC è lalibreria di comunicazione chiamata SyncUtils. Mentre le funzionalità diarchiviazione aggiuntive risiedono principalmente in GEC_Scan e nel-l’insieme dei suoi plug in, esse non potrebbero essere utilizzate da GECsenza l’ausilio di questa libreria: il suo scopo è quello di astrarre il meto-do di comunicazione dalle modalità tecniche con le quali le comunicazionieffettivamente avvengono.

L’ambiente nel quale il sistema progettato deve operare prevede:

• molti software di scansione (GEC_Scan) che hanno a disposizionevarie sorgenti di dati e vengono manovrati da operatori umani;

• uno o più software di controllo (GEC) che possano richiederead uno dei software di scansione di cominciare una sessione diacquisizione.

GEC_Scan deve essere in grado di accettare una richiesta di inizio proce-dura di acquisizione, gestirla autonomamente e inviare alla fine la notificadell’avvenuto lavoro senza tenere GEC in sospeso, permettendogli cosìdi gestire nel frattempo eventuali altre comunicazioni.

13

Page 20: Tesi Todone

14 3. SyncUtils

Siamo perciò interessati ad un tipo di comunicazione nella quale—nelcaso peggiore (facendo riferimento alle figure 2.1 nella pagina 6 e 3.1):

• come attori, sono coinvolte m istanze di GEC in versione installa-bile (al massimo una per macchina), n istanze remote di GEC inversione ASP, i istanze di GEC_Scan (al massimo una per macchi-na), con i, m ed n numeri imprecisati non necessariamente uguali,maggiori di 1;

• ogni attore può prendere l’iniziativa di parola;

• ogni GEC in versione installata può parlare col GEC_Scanpresente sulla sua stessa macchina (se presente);

• ogni GEC in versione ASP può parlare con qualsiasi GEC_Scan;

• ogni GEC_Scan può parlare con GEC installato sulla sua stessamacchina e con qualsiasi altro GEC in versione ASP.

Cioè: ogni utente col suo calcolatore deve poter usare la sua unicacopia di GEC_Scan facendola interagire con un GEC installato sulla suastessa macchina e/o con un certo numero di altri GEC remoti.

3.2 Architettura

Si assuma che ogni copia di GEC_Scan abbia accesso in lettura e scrit-tura ad una porzione privata del file system dell’elaboratore sul qualeè installato; chiunque voglia dialogare con esso (ad es. GEC installatoo GEC versione ASP) dovrà poter avere accesso in lettura e scritturaalla stessa porzione del file system (per brevità di seguito “file system” o“FS”).

La comunicazione è dunque a mezzo condiviso, nel senso che gli attoriche dialogano tra loro di volta in volta devono condividere un file systemcui hanno accesso; per analizzare il caso più generale continueremo adire che ogni GEC condivide con l’i-esimo GEC_Scan il file system i (oFS-i).

Le richieste vengono effettuate da un GEC scrivendo nel FS-i deifile con estensione .IN contenenti i dettagli delle richieste in formato

Page 21: Tesi Todone

Architettura 15

XML ( 3.3.6 nella pagina 28); le risposte al termine di una sessione diacquisizione vengono fornite da GEC_Scan scrivendo nel FS-i dei filecon estensione .OUT e nome file uguale alla corrispondente richiesta.

GEC GEC

GEC

GEC_Scan-i

ASP

ASP

FS-i

Figura 3.1: Schema dell’utilizzo concorrente da più istanze di GEC del

file system i, associato alla i-esima istanza di GEC_Scan.

Naturalmente, più processi potrebbero accedere contemporaneamen-te ad uno stesso file system; è tuttavia stato approntato un meccanismodi mutua esclusione (descritto in 3.3.2 nella pagina 21):

• per fare in modo che ogni richiesta abbia un nome univoco sulfile system i;

• per garantire che più GEC concorrenti nell’effettuare una richiestaallo stesso GEC_Scan non si intralcino a vicenda;

• per fare in modo che le richieste siano ordinabili—per istante diarrivo—in una coda.

Page 22: Tesi Todone

16 3. SyncUtils

Un attore che voglia prendere possesso del mezzo comunicativo costitui-to dal FS-i, per prima cosa utilizzerà detto meccanismo impedendo aqualunque altro attore di impadronirsi a sua volta del file system.

Ovviamente non sempre un attore riesce a prenotare l’uso esclusivodel file system, ad esempio quando questo è già in uso da un altro attore;in seguito ( 3.3.2 nella pagina 21) si darà spiegazione dei dettagli delmeccanismo: si dica “tentativo di acquisizione del lock ” il tentativo diimpadronirsi del mezzo di comunicazione, e “acquisizione del lock ” ilprovare reiteratamente ad acquisire il lock finché non si abbia successo.

La generazione di un nome file univoco nel FS-i, necessaria per lascrittura dei file .IN dipende da una stringa originata a partire dalla da-ta/ora della sua creazione: questa stringa e l’entità che essa rappresentaassumono il nome di JobId. Definiamo quindi un JobId come l’iden-tificativo univoco all’interno di un file system, utilizzato per identificareesattamente richieste e relative risposte.

Ogni file di nome {JobId}.IN contiene delle informazioni organiz-zate in un’entità chiamata Request; ogni file di nome {JobId}.OUTcontiene dati relativi ad un’entità di tipo Response.

Come si può osservare in figura 3.2 nella pagina successiva, ogniRequest contiene:

• una o più ActionRequest;

• uno e un solo AdditionalData;

• un Timestamp.

In ottica di programmazione ad oggetti, ActionRequest eAdditionalData sono solo delle classi base astratte, atte a definirel’archetipo dei campi contenuti in ogni richiesta: una Request ben for-mata non conterrà mai direttamente una ActionRequest, bensì unaclasse derivata da essa (similmente per AdditionalData ed altre clas-si simili); d’ora in avanti per “una ActionRequest” ad esempio, siintenderà una qualsiasi entità che derivi da ActionRequest e non unoggetto di tipo ActionRequest, se non diversamente specificato.

Page 23: Tesi Todone

Architettura 17

Document

ActionResponse

ResponsePageResponsePage

ResponsePageResponsePage

ActionResponse

Page

Page

Page

Page

Request

ActionRequest

ActionRequest

AdditionalData

Document

ActionResponseResponsePage

ResponsePageActionResponse Page

Response

Figura 3.2: Esposizione grafica della struttura di Request e Response; le

frecce indicano che l’oggetto d’origine mantiene internamente un riferimento

all’oggetto puntato.

Le azioni intraprese da GEC_Scan alla ricezione di una Requestdipendono dal tipo specializzato di ogni ActionRequest contenuta;AdditionalData contiene dei meta dati che devono essere interpreta-ti da GEC_Scan per soddisfare correttamente ogni richiesta e possonoessere associati ai documenti acquisiti.

Page 24: Tesi Todone

18 3. SyncUtils

Per quanto riguarda Response essa contiene sempre:

• la sezione Documents;

• la sezione Errors, relativa agli errori generici di comunicazione.

Si ponga attenzione sul fatto che un documento è stato definito comeun’insieme di una o più immagini: finora non si è parlato di alcun limiteal numero di immagini acquisibili dall’utente, o di vincoli sul modo diraggrupparle in documenti; quindi nè il numero di documenti che ver-ranno elaborati nè il numero di pagine di ognuno di questi è predicibilesalvo casi particolari1.

Per questi motivi, in una Response

• Documents contiene uno o più oggetti Document, entitàrappresentante un gruppo di immagini;

• ogni Document contiene una lista di oggetti Page, entitàrappresentanti le singole immagini scansionate dall’utente;

• ogni Document contiene una o più ActionResponse (conconsiderazioni simili al caso di ActionRequest);

• ogni ActionResponse rappresenta il rapporto su una solaazione intrapresa per il Document che la contiene in seguitoall’elaborazione di una ActionRequest;

• ogni ActionResponse contiene una lista di ResponsePage,enumerazione delle azioni intraprese sulle singole Page delDocument.

Anche in questo caso l’esatto contenuto di una ActionResponse dipen-de dalla classe specializzata che la estende. Si pensi al seguente esempiopratico: si ha la necessità di archiviare una fattura del signor Mario Ros-si presso un servizio di archiviazione remota chiamato “MyArchive”; atale scopo saranno stati precedentemente definiti alcuni tipi specializzaticome

1In realtà GEC può richiedere un numerno minimo ed uno massimo di gruppi diimmagini (vedi 4.1.1 nella pagina 47).

Page 25: Tesi Todone

Architettura 19

• SendToMyArchiveActionRequest;

• SendToMyArchiveActionResponse;

• SendToMyArchiveActionPerformer;

• SendToMyArchiveResponsePage;

derivanti rispettivamente da

• ActionRequest;

• ActionResponse;

• ActionPerformer;

• ResponsePage.

In più, per veicolare correttamente i dati relativi ad una fat-tura, InvoiceAdditionalData è stato derivato—con l’ag-giunta di appositi campi—da AdditionalData. A que-sto punto è possibile costruire una Request contenente adesempio una sola SendToMyArchiveActionRequest ed unInvoiceAdditionalData.

SendToMyArchiveActionRequest conterrà informazioni relativel’indirizzo al quale raggiungere il servizio MyArchive edimpostazioni simili;

InvoiceAdditionalData potrebbe contenere l’anagrafica del signorMario Rossi e ogni altro dato utile ai fini della compilazione deimeta dati associati ai documenti veri e propri.

Se l’utente ha acquisito due documenti da tre pagine ciascuno, con tale ri-chiesta è lecito aspettarsi una risposta per cui vi saranno due Documentcontenenti tre Page e una SendToMyArchiveActionResponse cia-scuno; ogni SendToMyArchiveActionResponse conterrà a sua voltatre SendToMyArchiveResponsePage, ognuna delle quali—facendoriferimento ad una singola Page—fornirà ad esempio informazioni sulsuccesso o meno dell’archiviazione, un link per recuperare l’immaginecorrispondente ecc. . .

Page 26: Tesi Todone

20 3. SyncUtils

Tutti i tipi specializzati, finalizzati a specifiche richieste, sono defi-niti nei moduli aggiuntivi chiamati plug in, caricati in modo dinamicoall’avvio di GEC_Scan.

3.3 Dettagli implementativi e tecnologie

Posto che GEC_Scan è un modulo software a se stante, anche il soloaggiungere a GEC le funzionalità di comunicazione con quest’ultimo ri-chiede necessariamente la modifica del programma e l’aggiunta di moltocodice.

Integrare direttamente in GEC queste capacità sviluppandole in Vi-sual Basic 6—lo stesso linguaggio in cui è stato scritto—sarebbe potutasembrare una buona idea: al contrario, aggiungere a del codice già ma-turo una ulteriore complessità per quanto lieve, potrebbe portare a deiproblemi di manutenibilità.

Se si aggiunge il fatto che il kit di sviluppo di Visual Basic 6 è allafine del suo ciclo di vita, si capisce come sia stato preferibile comporre ilsistema di comunicazione con una tecnologia più moderna: si è scelto disviluppare con dotNet e la tecnologia COM del codice che—proprio dalpunto di vista del ciclo di vita—è autonomo e interfacciabile con GECcon un ridotto numero di modifiche a quest’ultimo.

La libreria SyncUtils è utilizzabile da codice dotNet come un qualsiasialtro assembly e (previa registrazione di alcuni tipi, 3.4 nella pagina 40)come componente COM.

3.3.1 Perché il file system?

La comunicazione tra sistemi informatici è sempre un ambito insidiosoe ricco di difficoltà, spesso nemmeno troppo palesi; anche per questomotivo, nell’affrontarlo si tenta quasi sempre di evitare di reinventare laruota: come in molte altre situazioni ci si affida più il possibile a soluzionigià note ed affermate, almeno per i problemi più comuni.

Nel caso in esame, ci si trova nella situazione abbastanza tipica di unsoftware (GEC_Scan) che pur eseguendo sull’elaboratore di un utentefinale (ed essendo perciò molto probabilmente isolato dalla rete da un

Page 27: Tesi Todone

Dettagli implementativi e tecnologie 21

firewall e da un sistema NAT/NAPT) deve comportarsi come server,attendendo richieste e non iniziandole.

Le possibili soluzioni note che usino protocolli consueti comeTCP/IP, sarebbero comunque state tutte piuttosto complesse da metterein pratica: fortunatamente il sistema ASP—come già accennato—mettea disposizione un file system condiviso tra i suoi utilizzatori.

L’utilizzo di un file system condiviso per la sincronia tra processi, laregolamentazione di accesso esclusivo a risorse e lo scambio di informazio-ni, è una pratica da tempo largamente diffusa e di dimostrata efficacia2:lo studio di alcune specifiche Microsoft [8] ed alcuni esperimenti condotti,hanno consentito di giudicare tali metodologie idonee anche all’utilizzosu un file system condiviso con una macchina remota tramite il sistemaASP.

Ciò permette di delegare al gestore del file system alcune problemati-che descritte in seguito come l’atomicità della creazione di un oggetto disincronia, la sicurezza del canale trasmissivo, la capacità di comunicarein determinate condizioni.

3.3.2 Meccanismo di sincronizzazione

L’acquisizione del lock per il file system i, si effettua tramite la scritturain esso di un file—vuoto—di nome concordato che non possa colliderecon gli eventuali file .in e .out già presenti (attualmente esso si chiamalockfile.lck). Si dice che tale lock viene rilasciato quando il file vienecancellato.

Un attore che volesse acquisire il lock dovrebbe per prima cosa veri-ficare che tale file non esista già e solo in tal caso provvedere a crearlo;una volta creato, altri attori desiderosi di acquisire il lock rileverebberola presenza del file sopra citato e desisterebbero (o resterebbero in attesache il file venga rimosso, a seconda dei casi).

È di fondamentale importanza capire come l’operazione di verifica ecreazione del file di lock debba necessariamente essere atomica per gestirele eventuali situazioni di concorrenza: non è accettabile alcuna situazio-

2Basti pensare ai files di lock utilizzati da alcuni software di database o a quelliusati del popolare Microsoft Word per regolare l’accesso ai suoi documenti.

Page 28: Tesi Todone

22 3. SyncUtils

ne di inconsistenza come quella riportata di seguito a titolo d’esempio:nell’ordine

1. l’attore A vuole acquisire il diritto di parola, pertanto tenta disegnalarlo, provando a creare il file di lock ;

2. in un istante di tempo ravvicinato ad (1) l’attore B vuole acquisireanch’esso il diritto di parola, pertanto tenta di creare a sua voltail file di lock ;

3. A verifica che il file di lock non esiste;

4. B verifica che il file di lock non esiste;

5. A crea fisicamente il file di lock ;

6. B—visto il punto 4—crede che il file di lock non esista e losovrascrive.

Se il sistema di sincronia fosse prono ad un tale tipo di errore, due attoripotrebbero ritenere di essere ognuno l’unico autorizzato ad accedere alfile system in un dato istante di tempo, creando JobId non certamenteunivoci e sovrascrivendo potenzialmente l’uno i file dell’altro, portandocosì ad evoluzioni impredicibili nella comunicazione.

Il problema della atomicità delle operazioni di verifica e creazionedel file di lock viene risolto considerando che all’atto della creazione diun nuovo file, in ambiente Microsoft Windows si può indicare al sistemacosa fare nel caso in cui non sia possibile completare l’operazione (es:perché il file esiste già): sovrascrivere il file, accodare al contenuto osegnalare un’errore. Quando un attore desidera acquisire il lock, puòsemplicemente provare a creare il file, istruendo il sistema operativo asollevare un’errore in caso di fallimento: se non si riceve alcun errore illock è acquisito, altrimenti no.

Al sistema operativo si delega la responsabilità della consistenza delsuo file system; in caso di file system remoti, il sistema operativo chefornisce l’accesso remoto ad un file system da lui mantenuto si occupa digarantire la consistenza quando più processi tentino di creare lo stessofile [8].

Page 29: Tesi Todone

Dettagli implementativi e tecnologie 23

Per impedire che altri processi come un antivirus o lo stesso uten-te possano inavvertitamente interferire col meccanismo di sincronia, ilfile viene mantenuto aperto in modalità esclusiva per tutto il tempo didetenzione del lock : in questo modo è impossibile per chiunque altrocancellarlo, rinominarlo o modificarlo.

Nel caso il processo detentore del lock venga terminato, il file restascritto sul file system, ma la modalità esclusiva viene a mancare: ognieventuale altro processo in attesa di rilascio del lock non avrà speranzedi acquisirlo fino al prossimo riavvio di GEC_Scan che causa la puliziadei file residui di vecchie esecuzioni.

3.3.3 Identificativi di richieste e risposte

Richieste e risposte vengono scambiate tramite dei file di estensione .INe .OUT, diversi dal file di lock ma residenti nel suo stesso file system.Questi file hanno sempre il nome costituito da dodici cifre ed un trattinoorizzontale, che rappresenta il JobId del lavoro in questione.

Un JobId è stato definito come l’identificativo univoco all’internodi un file system, utilizzato per identificare univocamente richieste e ri-sposte. Esso viene generato a partire dalla data-ora della sua creazione;nell’implementazione C# è in realtà un oggetto che conserva come statointerno un timestamp, e permette di ricavare da questo una rappresenta-zione stringa nel formato yyyyMMdd-hhmmss dove “y” sono le quattrocifre corrispondenti all’anno, “M” quelle corrispondenti al mese, “d” algiorno, “h” all’ora, “m” ai minuti e “s” ai secondi.

Per creare un JobId valido (avendo certezza della sua univocità perun determinato file system) ed associarlo ad una richiesta si effettua laseguente procedura:

• si acquisisce il lock ;

• si crea a partire da data e ora correnti la stringayyyyMMdd-hhmmss;

• si usa la stringa come nome file, considerando che l’estensione peruna richiesta dev’essere .IN;

Page 30: Tesi Todone

24 3. SyncUtils

• se tale nome file esiste già, si incrementa di uno il numero indi-viduato graficamente da yyyyMMddhhmmss e si torna al puntoprecedente (senza preoccuparsi del fatto che il numero corrispondaancora ad una data-ora valida; es: 800419170261 non corrispondead una data-ora valida, ma è comunque valido come base per creareun JobId);

• si crea il file;

• si scrive una richiesta valida nel file;

• si rilascia il lock.

Una risposta ad una richiesta ha il suo stesso nome file ma con estensione.OUT; i file di richiesta e di risposta, contengono dati in formato chevedremo in seguito (vedi 3.3.6 nella pagina 28).

Spesso una risposta fornisce anche un certo quantitativo di dati—nel nostro caso, ad esempio le immagini catturate: formato e ubicazionedi questi dati sono indipendenti dal sistema di comunicazione, e deter-minati dai singoli plug in che gestiscono l’archiviazione (vedi 5.2 nellapagina 76), ma vengono comunque specificati in apposite sezioni nel file.OUT.

3.3.4 Protocollo

Di seguito vengono riportate in pseudo codice alcune delle procedure checostituiscono il protocollo di comunicazione3. Le procedure con prefissoGEC sono eseguite su iniziativa di GEC sulla macchina ove questo è inesecuzione, mentre quelle con prefisso SCAN si riferiscono al softwaredi scansione GEC_Scan. FS sta per file system. L’indice i riferisce ilprefisso al file system i-esimo. “Lavoro” o “Job” è il termine generico perindicare una richiesta, solitamente coincidente con la richiesta di iniziosessione di acquisizione.

3Protocollo studiato dal prof. Alberto Bartoli con l’aiuto della documentazioneprodotta dall’ing. Giorgio Davanzo; implementazione pratica in C#, sostituzionedell’active poll con sistemi di notifica e cura di dettagli tecnici pratici a cura diGiancarlo Todone.

Page 31: Tesi Todone

Dettagli implementativi e tecnologie 25

Algorithm 3.1 Lock-CleanUp: Da eseguire all’avvio di GEC_Scan.1: if EXISTS(lockfile-i) then2: TIMEOUT = 10sec3: BeginWait = now()4: while now() < BeginWait + TIMEOUT do5: if NOT EXISTS(lockfile-i) then6: break;7: end if8: end while9: DELETE lockfile-i

10: end if

Algorithm 3.2 GEC-RequestJob: Da eseguire per richiedere un lavoro.1: GET lock-i2: GET NEW JobId-i3: RELEASE lock-i

Algorithm 3.3 GEC-Abort: Da eseguire per annullare una richiesta dilavoro pendente su iniziativa di GEC, dato il suo JobId.1: GET lock-i2: DELETE request-file (filename = JobId.IN) in FS-i3: RELEASE lock-i

Algorithm 3.4 SCAN-CleanUp: Da eseguire all’avvio del programmadi scansione; FS-i viene riportato nello stato iniziale. Per semplicità,non si cerca di recuperare eventuali lavori effettuati nella incarnazioneprecedente ma non completati.1: EXEC Lock-CleanUp2: GET lock-i3: DELETE ALL response, data, request files (in quest’ordine)4: RELEASE lock-i

Page 32: Tesi Todone

26 3. SyncUtils

Algorithm 3.5 SCAN-Abort: Da eseguire per annullare (su iniziativadel software di acquisizione) una richiesta di lavoro pendente, dato il suoJobId.1: GET lock-i2: GENERATE EMPTY response-file (name = JobId.OUT) in FS-i3: RELEASE lock-i

Algorithm 3.6 SCAN-CompleteJob Da usarsi per segnalare ilcompletamento (andato a buon fine o meno) di una richiesta di lavoro.1: GET lock-i2: if EXISTS(Input) then3: CREATE data-files in FS-i4: CREATE Output-file in FS-i5: else6: DISMISS data7: end if8: RELEASE lock-i

In pratica:

• Per effettuare una richiesta, il GEC deve:

� acquisire il lock;� calcolare un JobId valido;� scrivere un file {JobId}.IN contenente la richiesta nel

corretto formato;� rilasciare il lock;� restare in attesa che venga scritto nella stessa posizione un

file con lo stesso nome ma estensione .OUT.

• Per recepire la richiesta ed effettuare una risposta, il GEC_Scandeve:

� restare in attesa finché sul file system predefinito non vienecreato un file con nome corrispondente ad un JobId validoed estensione .IN;

Page 33: Tesi Todone

Dettagli implementativi e tecnologie 27

� acquisire il lock;� leggere il contenuto del file di richiesta;� rilasciare il lock ;� elaborare la richiesta;� acquisire il lock ;� scrivere il file .OUT;� rilasciare il lock.

Come si può notare dall’ultima esemplificazione, l’elaborazione vienefatta da GEC_Scan mentre il lock non è mantenuto, per permette-re che altre comunicazioni avvengano mentre è in atto un processo diarchiviazione molto lungo.

Inoltre è visibile che se GEC_Scan notasse la presenza del file dirichiesta e tentasse di leggerlo prima che il GEC abbia finito di scriverlo,non vi riuscirebbe semplicemente perché prima dovrebbe acquisire il lockancora detenuto dalla controparte. Un analogo ragionamento si può fareper il file di risposta.

Se questo tipo di meccanismo da un lato permette una corretta evolu-zione delle dinamiche di comunicazione, dall’altro introduce anche dellesituazioni in cui i processi comunicanti si intralciano a vicenda, spre-cando delle risorse; per questo motivo nell’implementazione reale deglialgoritmi di comunicazione si sono previsti dei piccoli ritardi program-mabili, impostati poi a valori dedotti in modo sperimentale. Questi nonalterano in alcun modo la logica della comunicazione, ma minimizzano itempi di attesa attiva di ciascuna parte.

3.3.5 Problematiche delle notifiche

Inizialmente si erano concepite ulteriori due procedure:

SCAN-CheckForRequests con la quale il software di acquisizionecontrollava l’eventuale arrivo di nuove richieste;

GEC-CheckJobCompleted che si occupava di controllare—dal latodi GEC—se una richiesta fatta in precedenza non fosse statasoddisfatta.

Page 34: Tesi Todone

28 3. SyncUtils

Le due funzioni utilizzavano la tecnica dell’active poll, interrogando dicontinuo il file system sulla presenza o meno di determinati file. Consi-derato che questo caricava notevolmente i file system (e in minor parteanche la rete, in caso di sistema acceduto da remoto) si è provvedutoa modificare il meccanismo in modo da utilizzare strumenti chiamatiFileSystemWatcher [9].

Questi consistono fondamentalmente in hook4 di sistema alle funzionidi base di accesso al disco, che sollevano un evento quando si presentanodeterminate condizioni, come il tentativo da parte di un programma discrivere un nuovo file in una cartella.

Purtroppo, come rilevato anche da una nutrita schiera di utenti5,il codice che implementa questa tecnica a volte ha dei comportamentiinattesi quando eseguito in ambiente Microsoft Windows 2003 Server.

All’epoca della prima stesura del programma non erano disponibilidei work around efficaci o soluzioni pubbliche: si è stati costretti a svi-luppare una soluzione alternativa poi segnalata sulla pagina ufficiale dibug report6.

La soluzione consiste nel sopperire ai comportamenti inattesi con de-gli snapshot della cartella ove avvengono gli scambi dei file: se tuttofunziona come da specifiche Microsoft, l’esecuzione procede normalmen-te e le operazioni sul file system generano le notifiche attese; se invecequalcosa dovesse andare male, viene richiamato un gestore d’errore condel codice d’emergenza che confrontando il sotto albero della cartella almomento dell’errore con quello stimato durante le esecuzioni corrette, loaggiorna e genera le notifiche di conseguenza.

3.3.6 Formati dei file di comunicazione

Il formato interno dei file di comunicazione si basa su XML. Una richiestatipo, contenuto di un file .IN si presenta come nel listato 3.1.

4Tecnica di intercettazione e modifica al volo di dati comunicati tra funzioni disistema; può essere “installato” in una catena di messaggi o in mezzo ad una serie dichiamate a routine [10, 13].

5https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=337917

6https://connect.microsoft.com/VisualStudio/feedback/Workaround.aspx?FeedbackID=337917

Page 35: Tesi Todone

Dettagli implementativi e tecnologie 29

Listing 3.1: Esempio di XML generato da SyncUtils per effettuare una

richiesta.

1 <Request>2 <ActionRequest xmlns:xsi="http://www.w3.org/2001/

XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:type="SaveToFileActionRequest"ARQID="0">

3 <Performer name="SaveToFileActionPerformer" />4 <RequiredFileFormat>png</RequiredFileFormat>5 <Path>c:\lockpath</Path>6 </ActionRequest>7 <AdditionalData xmlns:xsi="http://www.w3.org/2001/

XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">

8 <OwnerID>64</OwnerID>9 <CustomerID>myCustomerID</CustomerID>

10 </AdditionalData>11 <Timestamp>2009-02-25T16:59:48.375+01:00</Timestamp>12 </Request>

Il codice XML viene generato semi automaticamente per serializza-zione di oggetti (vedi 3.3.7 nella pagina 32), quindi in questo frangente,con un nome ci si potrà riferire indistintamente al tag o alla classe chelo ha generato.

In 3.2 nella pagina 16 parlando della struttura del sistema di comu-nicazione, è stato detto che Request e Response reali contengono solotipi specializzati di ActionRequest, ActionResponse ecc. . . Nellistato di esempio è immediato però notare che i nomi dei tag di alcuneentità derivabili sono dati da quelli delle loro classi base; questo fa partedel meccanismo di serializzazione: il nome della classe specializzata ècontenuto in questi casi dall’attributo xsi:type. Non si fa affidamen-to a xsi:type per la corretta serializzazione del campo Performerche contiene semplicemente il nome della classe preposta a gestire laActionRequest che lo contiene.

In 3.2 nella pagina seguente si può osservare un esempio di risposta,contenuto nel file .OUT corrispondente ad un file .IN di richiesta.

Page 36: Tesi Todone

30 3. SyncUtils

Listing 3.2: Esempio di XML generato da SyncUtils per effettuare una

risposta.

1 <Response xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">

2 <Documents>3 <Document GID="0">4 <Pages>5 <Page PID="0" />6 <Page PID="1" />7 <Page PID="2" />8 </Pages>9 <ActionResponses>

10 <ActionResponse xsi:type="SaveToFileActionResponse" ARSID="0" Request="0">

11 <Errors />12 <Pages>13 <ResponsePage xsi:type="FSPage" Page="0"

Format="png" FileName="fileName1" />14 <ResponsePage xsi:type="FSPage" Page="1"

Format="png" FileName="fileName2" />15 <ResponsePage xsi:type="FSPage" Page="2"

Format="png" FileName="fileName3" />16 </Pages>17 <Path>c:\lockpath</Path>18 </ActionResponse>19 </ActionResponses>20 </Document>21 </Documents>22 <Errors>23 <Error IsCrytical="true" EID="0">24 Test error message 2 !25 </Error>26 </Errors>27 <Timestamp>2009-02-27T23:14:52.640625+01:00</Timestamp

>28 </Response>

Si possono notare gli attributi PID, GID, EID ecc. . . che fungono

Page 37: Tesi Todone

Dettagli implementativi e tecnologie 31

da identificatori univoci per l’entità cui appartengono all’interno delloro contenitore; in figura 3.2 nella pagina 17 le frecce indicano chel’oggetto da cui partono conserva un identificativo dell’oggetto punta-to, cui si riferiscono logicamente, come una ActionResponse indical’ActionRequest da cui è originata.

Il meccanismo di distribuzione degli identificativi è tale che unidentificativo sia univoco tra quelli degli oggetti contenuti nello stes-so contenitore (ad esempio: non ci sono ripetizioni tra gli id del-le ActionResponse in un medesimo Document, ma due id diActionResponse in due Document distinti possono essere ugualipoiché non è comunque possibile equivocare tra loro).

Dal punto di vista dell’implementazione, ogni oggetto che può funge-re da contenitore per altri oggetti mantiene internamente un oggettodi tipo IdFactory per la generazione consistente e la distribuzio-ne degli identificativi; tutti gli oggetti che possono venire identificatiper qualche motivo implementano l’interfaccia IHasId; tutti gli oggettiche possono fare riferimento ad un altro oggetto implementante IHasIdimplementano a loro volta l’interfaccia IIdPointer.

È forse doveroso ribadire che normalmente per individuare precisa-mente un oggetto manterremmo semplicemente una managed referencea quest’ultimo; ma questo tipo di riferimento, nella situazione propostaè di difficile espressione durante la serializzazione XML.

Listing 3.3: Riassunto dei meccanismi di distribuzione consistente degli

identificativi.

1 public interface IHasId2 {3 int Id { get; set; }4 }5

6 public interface IIdPointer7 {8 int PointedId { get; set; }9 void PointTo(IHasId item);

10 }11

12 public class IdFactory13 {

Page 38: Tesi Todone

32 3. SyncUtils

14 int _count = 0;15 ...16 public virtual IHasId SetID(IHasId item)17 {18 item.Id = _count++;19 return item;20 }21 ...22 }23

24 public class IdFactory<T> : IdFactory where T : IHasId,new()

25 {26 ...27 public override IHasId SetID(IHasId item)28 {29 ...30 return base.SetID(item);31 }32 }

3.3.7 Serializzazione XML

Le tecniche di serializzazione XML in generale, e quelle utilizzate secon-do le usanze del framework dotNet in particolare, sono estremamentenote in letteratura [12], ma è bene soffermarsi su certi loro aspetti pergli interessanti risvolti scaturiti durante lo sviluppo di alcune parti delsoftware di interscambio dati.

La serializzabilità di un tipo in ambito dotNet è cosa diversa dallasua serializzabilità XML: ai nostri scopi tutti i tipi primitivi sono XM-L-serializzabili e in aggiunta—grazie all’uso della reflection—anche moltitipi complessi non espressamente pensati in ottica di serializzazione XMLsono comunque XML-serializzabili.

Nel package System.Xml.Serialization si trovano gli strumen-ti per effettuare serializzazione e deserializzazione di oggetti secondo duemodalità che potremmo definire “esplicita” ed “implicita”:

Page 39: Tesi Todone

Dettagli implementativi e tecnologie 33

• nella modalità esplicita, gli oggetti candidati alla serializ-zazione devono implementare esplicitamente l’interfacciaIXmlSerializable, che prescrive l’implementazione di tremetodi per la serializzazione, la deserializzazione e la definizionedi uno schema;

• nella modalità implicita, il framework ispeziona tramite reflectionle classi degli oggetti da serializzare e considerando solo campi eproprietà pubbliche genera al volo un oggetto serializzatore adatto.

Nella maggior parte dei casi la modalità implicita è più che sufficiente,se si considera che è possibile istruire in certa misura il serializzatore sualcuni dettagli come nomi dei tag, tipo dei nodi ecc. . . mentre con la mo-dalità esplicita—che pur permette di risolvere problemi più complessi—ènecessario scrivere molto codice, introducendo problemi di leggibilità emanutenibilità del sorgente.

Solitamente si fa uso di una sola tecnica per volta, ma accade ancheche le due vengano combinate, ad esempio quando si serializza un ogget-to implicitamente serializzabile che però serba in alcuni dei suoi campioggetti esplicitamente serializzabili; ciò che accade è esemplificato nelseguente algoritmo:

• se l’oggetto da serializzare è un tipo primitivo, allora è benconosciuto: si richiama una procedura standard per la suaserializzazione e si termina la procedura;

• se l’oggetto da serializzare implementa IXmlSerializable, al-lora si chiama il metodo IXmlSerializable.WriteXml() e sitermina la procedura;

• se l’oggetto non appartiene alle precedenti due categorie ma ècomunque XML-serializzabile, allora si itera l’algoritmo su ognicampo.

Analogamente per la deserializzazione. È ovvio che nel caso di un og-getto complesso con campi complessi tutti implicitamente serializzabili,

Page 40: Tesi Todone

34 3. SyncUtils

l’algoritmo itera finché non è stato analizzato l’intero albero7; è altresìvisibile che qualora venga incontrato un oggetto IXmlSerializable,i suoi metodi WriteXml/ReadXml si occuperanno della sua interaserializzazione/deserializzazione, fermando la ricorsione dell’algoritmosummenzionato.

Nello sviluppo del progetto si sono affrontati dei casi in cui ciò rappre-senta un problema: gli oggetti che gestiscono richieste e risposte utilizza-no meccanismi di serializzazione complessi, poichè gli oggetti scambiatidurante una comunicazione non sempre sono ben conosciuti da entram-bi gli interlocutori; quindi questi oggetti implementano esplicitamente imeccanismi con IXmlSerializable. Nonostante ciò, per semplificarelo sviluppo futuro di ulteriori oggetti contenuti in richieste e risposte, sidesidera che tali oggetti non debbano necessariamente implementare essistessi le loro procedure di serializzazione in maniera esplicita.

È stato quindi adottato un espediente: nel codice di serializzazionepersonalizzato di Request e Response, ogni loro campo viene serializ-zato/deserializzato istanziando di volta in volta un nuovo serializzatore,che inizia nuovamente per ogni loro campo l’algoritmo descritto in pre-cedenza; i flussi di codice XML prodotto nelle singole serializzazioni diquesti oggetti vengono poi fusi col flusso principale dell’oggetto padre aposteriori (analogamente, durante la deserializzazione avviene l’estrazio-ne di porzioni di XML dal flusso principale che generano oggetti reinseritinegli appositi campi dell’oggetto padre a posteriori).

Tutti i tipi conosciuti da un’esecuzione della libreria di comunicazio-ne, vengono mantenuti in un registro statico e pubblico, accessibile daogni serializzatore; l’insieme di queste tecniche permette la serializzazio-ne/deserializzazione di tipi non noti a compile time, e la corretta gestio-ne della loro ereditarietà, mantenendo comunque semplice lo sviluppo difunzionalità aggiuntive.

7Per semplicità e compattezza vengono taciute le problematiche di visitacome ad esempio riferimenti incrociati e similari, pur esistenti ed affrontatidall’implementazione reale dell’algoritmo.

Page 41: Tesi Todone

Dettagli implementativi e tecnologie 35

3.3.8 COM

COM è acronimo di Component Object Model, un’architettura chepermette l’interfaccia di componenti software di varie parti senzache queste siano ricompilate in un progetto, al fine di promuovernel’interoperabilità.

Esso non è dipendente da un particolare linguaggio—ogni linguaggioche sia in grado di chiamare funzioni tramite puntatori può accedere allesue funzionalità—e si basa sui concetti di componente ed interfaccia.

Tali componenti ed interfacce sono conservati in delle DLL struttu-rate secondo un metodo prestabilito, e riferiti durante il loro utilizzosecondo un peculiare meccanismo di doppia indirezione: si mantiene ilriferimento ad un componente tramite l’indice di una tabella—chiamata“vtable”—che a sua volta conserva un’indirizzo reale alla struttura datidesiderata: in questo modo le vtable possono essere condivise da piùistanze di un oggetto riducendo l’utilizzo di memoria.

Un componente COM somiglia in struttura a ciò che è una classe perla programmazione ad oggetti.

In una gerarchia di classi, in qualsiasi contesto di programmazioneesiste un ancestor, ovvero il modello di un’entità di base con un insiememinimo di caratteristiche e funzionalità di base che qualsiasi altro oggettodeve possedere; in ambito COM, si dice che tale oggetto implementaalmeno l’interfaccia IUnknown.

Listing 3.4: Interfaccia IUnknown come appare in C++.

1 class IUnknown2 {3 virtual HRESULT QueryInterface(IID& iid, void**

ppvObj) = 0;4 virtual ULONG AddRef() = 0;5 virtual ULONG Release() = 0;6 }

Questa interfaccia prescrive l’implementazione di tre metodi:

Page 42: Tesi Todone

36 3. SyncUtils

QueryInterface permette di interrogare il componente imple-mentante circa il supporto o meno di un’altra specificainterfaccia;

AddRef viene chiamato per aumentare il conteggio interno degli uti-lizzatori (insieme a Release implementa un primitivo GarbageCollector);

Release decrementa il conteggio interno degli utilizzatori e libera lamemoria quando questo raggiunge lo 0.

Un componente COM può supportare un numero qualsiasi di interfaccea partire da un minimo di una (IUnknown); le interfacce possono essereprese dal programmatore tra alcune predefinite, derivate da esse o createex novo.

Per permettere la risoluzione degli identificativi univoci che contrad-distinguono componenti ed interfacce COM a partire da nomi, tali ele-menti devono necessariamente essere registrati, cioè iscritti ad elenchisiti in determinate aree del registro di configurazione di Windows8.

La tecnologia dotNet, con il suo proprio concetto di riusabilità stasoppiantando di fatto il Component Object Model, nonostante que-st’ultimo sia stato forse una delle tecnologie più usate dal 1993 adoggi9.

Il passaggio da una tecnologia all’altra viene reso più facile dallaprevista possibilità di interazione tra le due: questa opportunità si espli-cita con il Runtime Callable Wrapper (RCW) necessario per eseguireuna chiamata a un server COM da un client dotNet, e il COM CallableWrapper (CCW) per eseguire viceversa una chiamata a un server dotNetda client COM10. Come suggerito dai nomi, queste due entità sono del

8In realtà COM fu portato anche su sistemi operativi diversi da Windows e addi-rittura su macchine diverse dai PC compatibili; in questi sistemi la risoluzione degliidentificativi avviene in modo analogo ma implementativamente diverso; l’uso piùesteso di COM rimane quello su piattaforme Windows, dal 3.x fino alle più moderneXP, Vista e Seven.

9Nata nel 1993, questa tecnologia è stata menzionata con enfasi da Microsoft soloa partire dal 1997.

10Chiamiamo “client COM” una porzione di un programma in grado di utilizzare unservizio esposto da un oggetto COM; chiamiamo altresì “server COM” il componenteche espone tale funzionalità.

Page 43: Tesi Todone

Dettagli implementativi e tecnologie 37

codice di contorno aggiunto automaticamente ai componenti di una del-le due metodologie di sviluppo per essere interpretati ed utilizzati anchedalla controparte tecnologica.

��

Consumer CCW Class

Component RCW ConsumerU

nman

aged

Man

aged

Figura 3.3: Schema di funzionamento di RCW e CCW; nella prima riga un

componente dotNet richiama funzionalità da un provider COM; nella seconda,

del codice capace di richiamare funzionalità COM chiama codice dotNet tramite

il CCW.

Nonostante ogni CCW sia generato automaticamente dal runtimedotNet, le classi da esporre come componenti COM devono venire ade-guatamente preparate; l’ambiente integrato di sviluppo Visual Studio2008 offre degli automatismi per assolvere a questo compito, ma restapreoccupazione del programmatore decorare le classi dotNet con attributiatti ad istruire il runtime nella creazione dei CCW ad esse dedicati.

Fondamentali ComVisible che abilita il processo di wrapping eProgId che assegna il nome al componente. Eventuali altri attributida applicare possono essere Guid, che specifica un identificativo univocoaltrimenti assegnato automaticamente e DispId che specifica in manieraesplicita l’ordine in cui i metodi devono comparire in un’interfaccia11.

11Per la corretta compilazione del codice, se almeno un metodo di una classe è statodecorato con DispId, allora lo devono essere tutti all’interno della stessa classe.

Page 44: Tesi Todone

38 3. SyncUtils

Listing 3.5: Esempio della decorazione minima di un componente da esporre

tramite COM.

1 [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)]

2 public interface _JobId3 {4 string ToString();5 bool Equals(object value);6 void Increment();7 JobId Clone();8 }9

10 [ClassInterface(ClassInterfaceType.None)]11 [ProgId("SyncUtils.JobID")]12 [ComVisible(true)]13 public class JobId : _JobId14 {15 ...16 }

Una particolare menzione meritano la gestione degli eventi e quelladegli errori; mentre i secondi sono propagati automaticamente dal siste-ma semplicemente assegnando un codice d’errore ad ogni eccezione nongestita, l’utilizzo dei primi richiede del codice aggiuntivo.

Proprietà di un’interfaccia C# come potrebbe essere

1 event JobCompletedDelegate OnJobCompleted;

vengono viste in realtà dai client COM come una coppia di metodiper l’aggiunta e la rimozione di gestori d’evento

1 AddJobCompletedDelegate();2 RemoveJobCompleteDelegate():

ma per permettere ad un COM client di venire notificato da uncomponente, è necessario assegnare esplicitamente a quest’ultimo an-che un’interfaccia in cui si specifica il metodo da chiamare al verificarsidell’evento; del tipo

Page 45: Tesi Todone

Dettagli implementativi e tecnologie 39

1 [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)]

2 public interface UserEvents3 {4 void OnJobCompleted(JobId job, Response response);5 ...6 }

Dal punto di vista dell’utilizzo con Visual Basic 6, l’utilizzo di unoggetto COM richiede un file che ne specifichi le funzioni presenti: talefile—di estensione .tlb—viene chiamato “type library”, ed è generatoautomaticamente all’atto della registrazione di un componente. Impor-tando la type library, è poi possibile cominciare ad usare qualsiasi dei tipiivi definiti, curandosi di dichiarare con la clausola WithEvents quellidei quali si voglia usare la capacità di sollevare eventi.

Nel progetto del sistema di archiviazione proposto, le classi ad esserepredisposte per l’utilizzo come componenti COM sono essenzialmentequelle riguardanti la libreria della comunicazione, e in maggior dettaglioquelle che permettono a GEC di richiedere un servizio a GEC_Scan:

ClientSideFileSync;

Request;

Response;

ActionRequest;

ActionResponse;

Document;

DocInfo;

Page;

ResponsePage;

Error

Page 46: Tesi Todone

40 3. SyncUtils

e classi da queste derivate. Lo sviluppatore che intendesse creare ulterioriplug in aggiuntivi dovrà curarsi che le sue classi siano accessibili a clientCOM per permetterne l’uso da parte di GEC.

3.4 Installazione e preparazione dell’ambiente diesecuzione

Il software in tutte le sue parti è in fase di test, e non viene quindi ancoradistribuito al di fuori del contesto di sviluppo. Per questo motivo non èfornito di un programma di installazione e di istruzioni user friendly, masolo di note tecniche, la maggior parte delle quali messe insieme durantela soluzione di reali problematiche di set up, o collezione di alcuni branirilevanti dalla documentazione e dai commenti al codice sorgente.

I tre tipi di software prodotti eseguono in due ambienti eventualmentecoincidenti:

• il calcolatore che esegue GEC

• il personal computer dove viene eseguito il software di acquisizionee i suoi plug in

Per quanto riguarda il lato controllore, devono essere distribuiti assieme aGEC tutti gli assembly inerenti la libreria di comunicazione. Le seguentiDLL contenenti codice dotNet racchiuso in oggetti COM vanno copiatein una cartella apposita su un volume non rimovibile del PC e registratenell’ordine:

• CommonUtils.dll

• SyncUtils.dll

• SerializationSetupHelper.dll

• BasicPlugins.dll

• ClientSync.dll

che in buona parte dipendono da (e quindi richiedono anche)SimpleLogger.dll

Per la registrazione, è possibile utilizzare il comando

Page 47: Tesi Todone

Installazione e preparazione dell’ambiente di esecuzione 41

1 RegAsm.exe nomeDll

residente nella cartella%WINDIR%\Microsoft.NET\Framework\v2.X\Come si può notare, la cartella è parte integrante del framework dotNet2.x (dove “x” sta per qualsiasi numero), palesando che l’installazione delruntime dotNet 2.0 o superiore è un prerequisito.

Da osservare anche il fatto che gli assembly preparati per essere utiliz-zati come oggetti COM hanno bisogno di un trattamento particolare, uti-lizzando per la registrazione l’apposito regasm.exe al posto dell’usualeregsvr32.exe

Molte di queste librerie sono utilizzate anche dal lato del softwaredi acquisizione: anche se questo dovesse essere installato sulla stessamacchina di GEC, le librerie non possono essere condivise. Andrannoquindi replicate nella cartella dedicata solo al programma di scansione.

Page 48: Tesi Todone

42 3. SyncUtils

Page 49: Tesi Todone

Capitolo 4GEC_Scan

4.1 Requisiti e progetto dell’interfaccia utente

Il software di acquisizione GEC_Scan dev’essere funzionalmente inte-grato con GEC. L’utente, una volta installato il sistema, non deve averecoscienza che GEC_Scan è un programma diverso da GEC ma deveessere portato a considerarlo come una sua estensione: per ottenere que-sto risultato GEC_Scan deve essere eseguito all’avvio della macchina sucui è installato e rimanere nascosto finchè non si presenti un determinatoevento (come l’arrivo di una comunicazione da GEC) nel qual caso dovràessere mostrata una schermata adatta a gestire l’evento.

In questo modo, la finestra di GEC_Scan si comporterà come se fos-se un form dell’applicazione principale, lasciando trasparente all’utentetutta la gestione delle comunicazioni tra un software e l’altro.

GEC_Scan deve utilizzare SyncUtils o essere compatibile con il suometodo di comunicazione a file system condiviso: deve quindi avere ac-cesso in lettura e scrittura alla porzione del file system sul suo elaboratoreche viene acceduta da GEC tramite SyncUtils.

GEC_Scan deve poter accettare da GEC un numero qualsiasi dirichieste di inizio sessione di acquisizione a prescindere dal suo stato dioccupazione: se arrivano ulteriori richieste mentre l’utente sta operandoil programma per soddisfarne una, tali richieste vanno inserite in una

43

Page 50: Tesi Todone

44 4. GEC_Scan

coda di tipo First In First Out, e vanno presentate all’utente in ordineuna ogni volta che la precedente sia terminata.

L’utente deve essere posto in grado di valutare la lunghezza dellacoda e di annullare una o tutte le richieste senza interrompere il suolavoro corrente. A tale scopo deve essere presente un form separato daquello principale che permette di osservare in tempo reale l’occupazionedella coda.

GEC_Scan deve poter comunicare con il maggior numero possibile diperiferiche di acquisizione come scanner, fotocamere e basi di dati; taleconnettività deve però essere assolutamente trasparente, cioè: il com-portamento e l’apparenza grafica del programma devono essere sempreuguali e garantire un’esperienza di utilizzo consistente qualsiasi sia lasorgente di dati scelta.

Le immagini acquisite singolarmente o in gruppi, devono esserepresentate tramite piccole anteprime che permettano quantomeno diidentificare in linea di massima ogni documento.

Non ci deve essere un limite—se non quello fisico della macchinadi esecuzione—al numero di immagini acquisibili e gestibili: allo sco-po di facilitare la gestione delle immagini (operazioni di ispezione, se-lezione, riordino, rotazione) il programma deve essere provvisto di unvisualizzatore integrato, che permetta di ingrandire le piccole anteprimee presentare le immagini a più alta risoluzione a vari livelli di zoom.

4.1.1 Interfaccia grafica e usabilità

Normalmente il programma di acquisizione documenti viene eseguito al-l’avvio del sistema dell’utente, ma la maggior parte delle sue funziona-lità è preclusa finché GEC—a seguito di un’operazione dell’utente—noninizia una sessione; per l’utente è tuttavia sempre possibile accedere tra-mite icona nella barra dell’orologio ad un menu di opzioni che permettedi impostare:

• il dispositivo da utilizzare tra una lista di scanner, fotocamere edaltre sorgenti TWAIN disponibili sul sistema;

Page 51: Tesi Todone

Requisiti e progetto dell’interfaccia utente 45

Figura 4.1: Finestra di opzioni del programma di acquisizione.

• la risoluzione (impostata alla prima esecuzione sulla risoluzio-ne disponibile più vicina—possibilmente per eccesso—a 300 dpi,risoluzione richiesta dalla maggior parte dei software OCR);

• modalità di colore (impostata alla prima esecuzione sulla modalitàpiù semplice che si avvicini a RGB);

• orientamento pagine (impostato alla prima esecuzione a 0º);

• utilizzo dell’alimentatore automatico fogli (se disponibile, imposta-to a vero alla prima esecuzione);

• utilizzo della scansione automatica fronte e retro (inizialmentefalso);

• utilizzo dell’eliminazione automatica pagine vuote (inizialmentefalso);

• utilizzo della rotazione automatica pagine (inizialmente falso);

Page 52: Tesi Todone

46 4. GEC_Scan

• utilizzo del rilevamento automatico delle dimensioni di una pagina(se disponibile inizialmente vero);

Ogni controllo di impostazione risulta operabile se pertinente, e nonpresente o disegnato in grigio se non disponibile o non applicabile.

Ogni impostazione si riferisce al dispositivo correntemente seleziona-to: scegliere un’altra periferica causerà l’adattamento dei parametri allecapacità della nuova sorgente scelta.

Alla chiusura della finestra delle preferenze, queste vengono reseufficiali e salvate su disco.

Figura 4.2: Schermata principale del programma di acquisizione.

Quando l’utente effettua in GEC un’operazione che causa l’inizio diuna sessione di acquisizione, la schermata principale del programma discansione compare in primo piano.

Tramite il tasto “Acquisisci” si inizia la scansione dalla periferica sele-zionata di una o più pagine dipendentemente dalle preferenze impostate:eventuali operazioni lunghe comporteranno la comparsa di un indicato-re di avanzamento che consente anche di interrompere le operazioni incorso.

Ad esempio, un’operazione di acquisizione molto lunga potrebbe pre-sentarsi nel caso in cui si sia scelto di scansionare molti documenti con

Page 53: Tesi Todone

Requisiti e progetto dell’interfaccia utente 47

un trascinatore automatico, oppure nel caso si sia scelto di utilizzare unarisoluzione molto alta.

Una volta raccolte delle immagini, queste compaiono sotto forma diicone sullo sfondo grigio della finestra principale: passandoci sopra conil puntatore esse si ingrandiscono per permettere di comprendere megliodi che pagina si tratta e per consentire all’operatore di capire qual è ilfoglio correntemente puntato. Aumentando le dimensioni della finestra,aumentano anche quelle delle icone delle pagine.

Facendo doppio click su un’immagine, questa viene mostrata in unafinestra di anteprima, nella quale è possibile effettuare zoom (operandola rotella del mouse o i tasti + e -) sulle sue varie parti a fini di ispezione.

Tenendo premuto il tasto sinistro del mouse e trascinando, l’imma-gine puntata viene rimossa dalla sua sede per consentire di posizionarlain altra locazione: rilasciando il tasto sinistro, essa verrà inserita su-bito prima dell’immagine correntemente sotto il puntatore (locazioneevidenziata da una barra nera sfumata).

Una barra di posizionamento compare al di sotto delle immagi-ni quando queste sono troppe per essere contenute in una sola scher-mata: sia quando si scorrono semplicemente le immagini, sia duran-te le operazioni di trascinamento, avvicinandosi al bordo sinistro o de-stro il programma effettua automaticamente una carrellata—tanto piùvelocemente quanto più si è vicini al bordo.

Tenendo premuto il tasto sinistro del mouse sull’area recante la di-citura “inserisci separatore” e trascinando, viene creato un elemento se-paratore (delle sembianze di una barra nera verticale) che è possibilerilasciare tra due immagini secondo le modalità già viste: anche unavolta rilasciato un separatore, è sempre possibile riprenderlo e spostarlocome una immagine qualsiasi.

Verrà considerato “documento” o “gruppo” l’insieme delle pagine con-tenute fra due separatori (o tra un separatore e l’inizio/fine della lista):il programma può essere forzato da GEC a richiedere un numero mini-mo e un numero massimo di gruppi di pagine: è possibile sapere qualisono i vincoli lasciando il puntatore sull’area di inserzione separatore easpettando la comparsa di un fumetto contenente tali informazioni.

Facendo click destro su un’immagine o un separatore, appare unmenu contestuale con diverse opzioni auto esplicative:

Page 54: Tesi Todone

48 4. GEC_Scan

• ruota in senso orario;

• ruota in senso antiorario;

• elimina.

La pressione del tasto “cancella immagini” causa la cancellazione di tuttele immagini acquisite.

Una volta catturate, riordinate e divise le pagine è possibile annullaretutto il lavoro o proseguire con l’archiviazione dei dati; la differenza tra“cancella immagini” e “scarta” consiste proprio nel fatto che il primo co-mando lascia la finestra aperta per effettuare ulteriori operazioni, mentreil secondo chiude e manda contestualmente a GEC un messaggio di er-rore comunicandogli che non è stato possibile completare correttamenteil lavoro per annullamento da parte dell’utente.

Se nel frattempo erano pervenute altre richieste di inizio sessione(es: l’utente ha effettuato altre operazioni su GEC che hanno originatoaltre richieste), il programma lo palesa restando in attesa di istruzioni,altrimenti torna nel suo stato quiescente. In ogni momento è possibilecontrollare e gestire lo stato della coda di richieste tramite l’appositafinestra, richiamabile dalla tray icon.

Figura 4.3: Finestra di gestione della coda in caso di richieste multiple.

Page 55: Tesi Todone

Composizione di GEC_Scan 49

Infine, chiudendo semplicemente la finestra principale (con la classi-ca “x” in alto a destra) o tramite il tasto “Nascondi” senza scegliere dimemorizzare o scartare il materiale raccolto, si sospende la sessione dilavoro nascondendo la finestra, recuperabile (senza perdere alcun dato)tramite icona nella barra dell’orologio.

4.2 Composizione di GEC_Scan

GEC_Scan

codi

cepr

inci

pale

VisualSlideShowe interfacciagrafica

dotNetTwain

SyncUtils

Plug in manager

TWAIN

File System

WinForms\GDI

Plug in

Plug in

Periferiche

GEC

Utente

Serviziesterni

Figura 4.4: Composizione di GEC_Scan e sue relazioni con tecnologie ed

altre parti del progetto.

In figura 4.4, si può osservare l’architettura di GEC_Scan e le sue

Page 56: Tesi Todone

50 4. GEC_Scan

varie relazioni con tecnologie e altre parti del progetto. Di SyncUtils siè parlato nel capitolo 3 nella pagina 13, mentre dei plug in e del lorometodo di gestione si parlerà nel capitolo 5 nella pagina 73. Di segui-to è possibile invece approfondire gli altri due aspetti rimanenti legatiall’architettura di GEC_Scan: l’integrazione con TWAIN che permet-te l’accesso alle periferiche di acquisizione e la struttura dell’interfacciautente.

4.2.1 TWAIN

TWAIN è uno standard per l’interfacciamento con dispositivi di imagingquali fotocamere digitali, scanner, database di immagini, ecc. . . che dàil suo nome ad una libreria distribuita gratuitamente, punto di riferi-mento dal 1991 per chiunque voglia comunicare con suddetti dispositiviutilizzando un’interfaccia software comune e senza doversi cimentare condriver e protocolli proprietari. Il suo nome non è un acronimo, ma unarcaismo inglese per “due”, riferimento ad un racconto di Kipling1, voltoad enfatizzare la difficoltà di interfacciamento tra i molti sistemi diversiall’epoca della sua nascita.

Lo standard ha tentato di imporsi sulle due piattaforme PC e Mac,presentandosi sempre come una libreria dinamica e mantenendo nomen-clature e convenzioni consistenti nei due ambienti. In ambiente Micro-soft Windows, essa è presente come DLL a 16 bit dalle prime versioni diWindows 3.x e in epoca più recente anche a 32 bit.

Da poco è stata resa disponibile la versione 2.0 ufficiale di TWAIN:il fatto che esistano così poche versioni della libreria e che siano tuttecompatibili tra di loro (pur coprendo un arco di tempo di 18 anni), èesemplificativo del fatto che nonostante questo standard sia stato lar-gamente usato, non c’è stata nel suo campo un’evoluzione tecnologicaconsistente; purtroppo ciò significa anche che sono pochi gli adattamentia nuove tecniche, metodologie e filosofie di programmazione ai quali essoè stato sottoposto.

Le entità in gioco durante una sessione di utilizzo di TWAIN sono:

1“OH, East is East, and West is West, and never the twain shall meet” [6].

Page 57: Tesi Todone

Composizione di GEC_Scan 51

applicazione cioè il codice utilizzatore di TWAIN, che si preoccupa dicaricare la libreria e di inizializzare il sistema;

Data Source Manager (o Source Manager o DSM), ovvero la partecentrale della libreria TWAIN e sua principale complessità; si pre-occupa di mantenere un dialogo con l’applicazione da un lato e coni Data Source dall’altro;

Data Source (o Source o DS): ognuno rappresenta una periferica diacquisizione, ed è implementata dal driver di ogni dispositivo chesia aderente alle specifiche TWAIN.

application DSM

message-pump

DS

DS

Figura 4.5: Schema del sistema di comunicazione tra le parti del sistema

TWAIN; DSM incarna la maggior parte delle funzionalità di TWAIN, anche

se per TWAIN si intende pure l’insieme delle specifiche che riguardano ogni

aspetto della comunicazione tra applicazione e DS.

La comunicazione tra DS e DSM è trasparente per lo sviluppatoredell’applicazione, e pertanto in questa sede verrà ignorata; su piattaformaWindows la comunicazione tra applicazione e DSM avviene in due modidiversi a seconda della modalità di comunicazione:

• per impartire al DSM un comando, o richiedere un parametro inmaniera sincrona, l’applicazione effettua una chiamata a una fun-

Page 58: Tesi Todone

52 4. GEC_Scan

zione esportata dalla DLL di TWAIN, passando strutture conte-nenti comandi e richieste, ed eventualmente puntatori a strutturevuote da riempire con le risposte; tali procedure sono bloccanti;

• per ottenere notifiche asincrone dal DSM, l’applicazione predisponeun meccanismo per l’ascolto di determinati messaggi tramite lamessage-pump di Windows.

Anche quando il destinatario ultimo di un comando è un Data Source,tale comando viene impartito tramite il DSM; in ogni comando vengo-no specificati gli interlocutori (chi tenta di comunicare con chi, ad es:l’applicazione con un DS) tramite codici di identità assegnati nella faseiniziale, puntatori a strutture dati e la cosiddetta “tripletta operativa”,costituita da:

dataGroup che identifica la macro categoria alla quale si sta facendoriferimento;

dataArgumentType usato per stabilire il l’area funzionale dei dati(capacità di un dispositivo, evento, identità, ecc. . . ) forniti odesiderati;

messageId specifica l’azione da effettuare (get, set,querySupport, ecc. . . ).

dataGroup può essere:

control, per il controllo della sessione TWAIN;

image, per lavorare con dati costituenti immagini e periferichepertinenti;

audio (scarsamente utilizzato) per operare su dati audio.

Alcuni esempi di dataArgumentType includono:

Identity usato nella gestione dei Data Source;

Capability usato nella negoziazione delle capacità richieste ad unaperiferica;

Page 59: Tesi Todone

Composizione di GEC_Scan 53

PendingXfers col quale si richiedono dati sulla quantità di documentipendenti;

ecc. . .

Esempi significativi di messageId possono essere

Get per richiedere il valore di una certa variabile di stato;

Set per impostare il valore di una certa variabile di stato;

Reset per riportare alle impostazioni predefinite una variabile di stato;

QuerySupport per richiedere al sistema se una certa funzionalità (es.la capability di un DS) è supportata o meno;

ecc. . .

Visti gli esempi di possibili valori, una tripletta operativa tipo potreb-be essere: DG_IMAGE/DAT_IMAGEFILEXFER/MSG_GET che istruisceuna sorgente a trasferire un’immagine su un file. In tal caso, l’informa-zione inerente a quale DS deve essere usato nel trasferimento è passatocontestualmente come parametro, mentre altre opzioni come il formatodell’immagine, la locazione del file da creare, ecc. . . sono state imposta-te durante l’evoluzione della comunicazione con altri comandi ed altretriplette operative.

In figura 4.6 nella pagina successiva si può osservare lo schema delfunzionamento di TWAIN come automa a stati finiti. Una volta carica-ta la libreria e verificata la presenza del punto di ingresso DSM_Entry(1),(2), per poter acquisire un’immagine da una sorgente bisogna inizia-lizzare il source manager (3) e una delle sorgenti a disposizione (4); aquesto punto è spesso necessario effettuare una procedura di negozia-zione delle capacità del dispositivo associato alla sorgente dati (è unamacchina fotografica o uno scanner? Dispone di caricatore automaticodei fogli?) al termine della quale si provvederà all’impostazione dei para-metri richiesti e all’abilitazione della sorgente (5), il che causerà l’iniziodella procedura di acquisizione. Gli stati (6) e (7) sono raggiunti ciclica-mente durante il trasferimento dei dati acquisiti fino a che la proceduradi acquisizione viene terminata dall’applicazione o dal data source.

Page 60: Tesi Todone

54 4. GEC_Scan

Figura 4.6: Diagramma di TWAIN visto come macchina a stati (dalla

documentazione ufficiale di TWAIN 1.9 [5]).

Qualsiasi dato scambiato dall’applicazione da e verso TWAIN è carat-terizzata da tipo e contenitore; vi sono quattro tipologie di contenitore,ognuno dei quali può contenere un insieme di valori di uno tra quindicitipi. I tipi sono:

bool: valore vero o falso;

Fix32: numero di 32 bit a virgola fissa;

(U)Int8/16/32: interi segnati e non di varie dimensioni;

Page 61: Tesi Todone

Composizione di GEC_Scan 55

Frame: contiene due coppie di valori numerici che individuano un’arearettangolare;

Str32/64/128/255/512/1024: stringhe di varie dimensionifisse.

Mentre i contenitori sono:

OneValue: il contenitore più semplice, contenente un solo valore;

Array: può contenere N elementi;

Range: indica (tramite la specificazione degli estremi e di un passo) unagamma di valori consecutivi;

Enumeration: indica N elementi possibili, il valore selezionato didefault e quello corrente.

Ad esempio, facendo una richiesta della capacità di risoluzione di undispositivo ottico, si otterrà probabilmente in risposta un Array diFix32.

Da notarsi che le strutture accettate o restituite da TWAIN si com-portano come varianti. In alcuni casi, non si sa che tipo di contenitoreviene ricevuto o il tipo di dati in esso contenuti se non leggendone ilcodice negli appositi campi di ogni struttura.

Nell’esempio sopra riportato, il dispositivo avrebbe potuto anche ri-spondere con un OneValue contenente un intero; sebbene per la maggiorparte delle operazioni siano ben documentati i tipi di contenitori e daticoinvolti, per compatibilità con periferiche che non si comportano rigo-rosamente come prescritto dallo standard, o per scalabilità sulle versionifuture di TWAIN, è bene fare meno assunzioni possibile sui tipi di datimaneggiati.

4.2.2 VisualSlideShow e design delle classi coinvolte

Nello sviluppo dell’interfaccia grafica si è voluto concentrare la maggiorparte della complessità in un unico componente grafico riutilizzabile chia-mato VisualSlideShow; ogni caratteristica dell’interfaccia utente non co-perta da tale componente, è stata ottenuta tramite l’utilizzo del designergrafico di Visual Studio e codice ad hoc.

Page 62: Tesi Todone

56 4. GEC_Scan

Questo controllo—destinato a contenere le icone di anteprima deifogli scansionati—consente di mantenere e presentare in maniera este-ticamente piacevole e funzionale, una grossa lista ordinata di immaginidivise per gruppi, effettuando automaticamente animazioni, caching e ri-dimensionamento delle icone di anteprima, e notificando autonomamenteil programma utilizzatore di eventuali modifiche alla lista.

Per far ciò si sono sviluppate delle classi dedicate, ed utilizzate altredi utilizzo più generale sviluppate per altre parti del progetto. In alcunicasi si è tentato di generalizzare il più possibile il design per massimizzareil riutilizzo del codice.

Ciò che si voleva ottenere era un componente che graficamente pre-sentasse delle caratteristiche complesse, ma che dal lato del codice sicomportasse come una semplice collezione di immagini.

Questo è stato possibile fondamentalmente grazie a tre tecniche:

• l’utilizzo di etichette;

• l’implementazione di interfacce multiple;

• l’utilizzo di eventi.

Ci sono alcuni casi (cfr. in C# le classi sealed [11] come ad esempioImage) in cui una classe non si può estendere; in questo e in altri casi ovesi vogliano aggiungere campi ad un entità senza ricorrere al polimorfismo,è possibile utilizzare il semplice meccanismo delle cosiddette etichette.

Dev’essere creato un oggetto con due campi: uno per l’oggetto daetichettare ed uno per l’etichetta; entrambi possono venire lasciati ditipo parametrico per un più agevole riutilizzo.

Oggetti etichettati di questo tipo possono servire ad aggiungere alleliste dati collegati ai loro corrispondenti meta dati; eventualmente si puòfare in modo che un TaggableItem<TItem, TTag> ritorni vero inun test d’uguaglianza con un’altro TaggableItem<TItem, TTag> sei due TItem sono uguali, o che un TaggableItem<TItem, TTag> siauguale a un oggetto di tipo TItem se quest’ultimo equivale all’oggettocontenuto nel TaggableItem.

Le collezioni di cui necessitiamo devono:

Page 63: Tesi Todone

Composizione di GEC_Scan 57

ITaggedItem<TItem, TTag>—

TItem ItemTTag Tag

TaggedItem<TItem, TTag>—

TItem ItemTTag Tag

Figura 4.7: Struttura di TaggedItem.

• poter essere enumerate come collezioni diTaggableItem<TItem, TTag> o come semplici collezionidi TItem;

• poter sollevare un evento ogniqualvolta la collezione venga inqualche modo alterata;

• essere facilmente estendibili a loro volta per aggiungere ulteriorifunzionalità.

Si è scelto di creare la classe TriggeringCollection<T> sfruttandole caratteristiche di base della classe Collection<T> e implementandoun’interfaccia ITriggeringCollection<T> come schematizzato infigura 4.8 nella pagina seguente.

L’interfaccia ITriggeringCollection<T> fornisce i metodi dibase per registrare un gestore di evento e per inibire o consentire lasollevazione di messaggi di evento.

TriggeringCollection<ITaggedItem<Image,TTag>> è sta-ta usata come base per TTTImageCollection<TTag>, che aggiungela possibilità di enumerare il contenuto della lista ignorando le etichette,e la generazione—e gestione—automatica delle anteprime.

Page 64: Tesi Todone

58 4. GEC_Scan

Collection<T> ITriggeringCollection<T>

IList<T>

TriggeringCollection<T>

Figura 4.8: Schema di ereditarietà ed implementazione interfacce di

TriggeringCollection.

TTTImageCollection<DisplayInfo> viene utilizzato da Vi-sualSlideShow per la gestione della sua collezione di immagini.

4.3 Tecnologie e tecniche implementative

Uno dei problemi principali durante la stesura del codice è stato l’inter-pretare metodologie di programmazione datate (basate molto sull’uso difunzioni statiche, costanti e di macchine a stati piuttosto che su qualcosache assomigli ad una gerarchia di classi) in modo coerente con la filosofiaobject oriented (di seguito anche OO oppure OOP) dell’ambito dotNet.

L’interazione con lo standard TWAIN ad esempio prevede chiamatead una sola funzione nativa che a seconda del valore di un buon numerodi parametri fa da interfaccia con la totalità delle funzioni di controllodegli scanner.

Le possibilità offerte dal framework per risolvere alcuni dei problemicome quello descritto partono da un livello piuttosto basso: l’interfac-ciamento del codice managed col codice nativo, la capacità di mappareuna classe su un record e la possibilità di generazione dinamica a tempodi esecuzione di strutture e byte code eseguibile.

Page 65: Tesi Todone

Tecnologie e tecniche implementative 59

TriggeringCollection<ITaggedItem<Image, TTag>>

TTTImageCollection<TTag>

Figura 4.9: Ereditarietà di TTTImageCollection: è una triggering list di im-

magini etichettate; VisualSlideShow usa internamente una TTTImageCollec-

tion<DisplayInfo> dove “DisplayInfo” sono meta dati associati alle immagini

utili durante il rendering del componente.

D’altra parte, la programmazione dell’interfaccia grafica non ha postoparticolari problemi se non quelli relativi alla rapidità di esecuzione edaffidabilità anche in presenza di una mole importante di dati da gestire.

Di seguito alcune tecniche e dettagli implementativi relativi aentrambi gli aspetti.

4.3.1 dotNetTwain

La libreria dotNetTwain reinterpreta TWAIN permettendo al codice chela utilizza di mantenere le usanze diffuse in ambito dotNet—e C# inparticolare—traducendo tipi varianti in generici, fornendo metodi di ap-poggio, ed in generale incapsulando gran parte dei complessi meccanismidi comunicazione di TWAIN. Nonostante ciò, la sua funzione principaleresta quella di fare da tramite tra i mondi managed e nativo.

L’interfacciamento di codice gestito con del codice nativo si esplicitain due modi:

• eseguire del codice nativo richiamandolo da codice dotNet;

Page 66: Tesi Todone

60 4. GEC_Scan

• eseguire del codice dotNet richiamandolo da codice nativo.

Mentre la seconda questione concerne l’uso di COM, la prima—qualora il codice da richiamare sia già racchiuso in una DLL—si risolve utilizzando i servizi esportati dal package dotNetSystem.Runtime.InteropServices. A questo punto si possonoseguire due strade a seconda delle necessità:

• utilizzare il link statico di ogni funzione desiderata esportata dallaDLL;

• utilizzare il link dinamico e ispezionare a run time le possibilitàofferte dalla DLL.

È doverosa a questo punto una precisazione: mentre il link statico è dirapido utilizzo per il programmatore e leggero da gestire per il sistema (ledimensioni del codice compilato sono ridotte e i tempi di inizializzazionesono minori rispetto al caso dinamico), esso comporta delle limitazioni.

Ad esempio non consente una gestione user friendly degli errori: nelcaso una libreria sia assente, o contenga codice sostanzialmente diversoda quello che ci si aspettava, in caso di link statico, il progetto utilizza-tore fallirà durante la sua inizializzazione senza permettere di gestire inqualche modo l’errore e senza consentire di avvisare l’utente con messaggiper lui più significativi.

Viceversa, il link dinamico permette una gestione più completa delledipendenze, ma è più complesso e dipende a sua volta da funzioni di cuiè necessario fare il link statico.

Entrambi i metodi sono dunque utilizzati per gestire la libreriaTWAIN.

Per effettuare il link statico con una funzione nativa presente in unaDLL da codice dotNet, è necessario definire nei sorgenti il prototipo diuna funzione statica all’interno di una classe, e decorarlo poi con l’at-tributo DllImport("libName.dll"), dove libName è il nome dellalibreria che come di consueto verrà cercata prima nella stessa cartelladell’eseguibile, poi in alcune cartelle di sistema.

1 using System.Runtime.InteropServices;2 class DllWrapper {

Page 67: Tesi Todone

Tecnologie e tecniche implementative 61

3 [DllImport("user32.dll"), EntryPoint="MessageBoxT"]4 public static extern int MessageBox (int h, string m,

string c, int type);5 }

Si può notare che nel prototipo della funzione i tipi dei parametri(come string) sono tipi dotNet: il marshalling di eventuali tipi com-plessi è quando possibile automatico, ed altrimenti specificabile tramitel’attributo MarshalAs.

1 [DllImport("Advapi32.dll", EntryPoint="GetUserName"]2 static extern bool GetUserName( [MarshalAs(UnmanagedType

.LPArray)] byte[] lpBuffer, [MarshalAs(UnmanagedType.LPArray)] Int32[] nSize );

Per utilizzare invece la tecnica del linking dinamico, ci si avvale diuna funzione introdotta con la versione 2.0 del framework dotNet:

1 Marshal.GetDelegateForFunctionPointer(IntPtr address,Type type);

questa caratteristica permette di tradurre in delegato (cioè puntatore afunzione managed) un puntatore reale ad una funzione nativa.

L’unico parametro mancante per poter usare questa tecnica è il pun-tatore alla funzione desiderata: nessuna funzione del framework ci con-sente di recuperarlo a partire—ad esempio—dal nome della funzione cheinteressa. Bisogna quindi adoperare il linking statico per avere acces-so a funzioni delle API di Windows che consentono di ottenere questeinformazioni.

Successivamente si potrà scrivere:1 delegate int MyFunctionDelegate(int a, int b);2 ...3 int libraryID = LoadLibrary("myLib.dll");4 IntPtr fnAddress = GetProcAddress(libraryID, "

functionName");5 MyFunctionDelegate myFunction = (MyFunctionDelegate)

Marshal.GetDelegateForFunctionPointer(myFunctionRealAddress, typeof(MyFunctionDelegate));

6 ...7 c = myFunction(a, b);

Page 68: Tesi Todone

62 4. GEC_Scan

Listing 4.1: Funzioni linkate staticamente per poter implementare un sistema

di link dinamico.

1 class DynamicLinkHelpers2 {3 [DllImport("kernel32.dll", EntryPoint = "LoadLibrary")

]4 static extern int LoadLibrary( [MarshalAs(

UnmanagedType.LPStr)] string lpLibFileName);5

6 [DllImport("kernel32.dll", EntryPoint = "GetProcAddress")]

7 static extern IntPtr GetProcAddress( int hModule, [MarshalAs(UnmanagedType.LPStr)] string lpProcName);

8

9 [DllImport("kernel32.dll", EntryPoint = "FreeLibrary")]

10 static extern bool FreeLibrary(int hModule);11 }

Se la libreria fondamentale kernel32.dll sarà assente, danneggia-ta o fondamentalmente diversa da quella che ci si aspetta, il program-ma terminerà in maniera repentina dando solo confuse informazioni tec-niche, mentre se la sola libreria denominata nell’esempio myLib.dlldovesse dare simili problemi, verrà sollevata un’eccezione normalmentecatturabile e gestibile.

Tutte le funzionalità offerte da TWAIN sono accessibili dall’unica fun-zione esportata da twain_32.dll, definita nel documento ufficiale [5]e nel file di definizione TWAIN.H come

1 DSM_Entry(IntPtr origin, IntPtr destination, uint32dataGroup, uint16 dataArgumentType, uint16 messageId,IntPtr dataPointer);

Richiede come primo parametro il puntatore ad una struttura cheidentifica l’applicazione: molte applicazioni possono fare uso contempo-raneamente di TWAIN, e per questo motivo esso mantiene uno statoassociato ad ognuna delle applicazioni con esso comunicanti; si usa con

Page 69: Tesi Todone

Tecnologie e tecniche implementative 63

origin impostata a null nella fase di acquisizione di un identificatore.Viene poi normalmente utilizzata in due possibili modi:

• per inviare comunicazioni dall’applicazione al source manager,impostando destination a null;

• per inviare comunicazioni dall’applicazione a una sorgente,impostando destination all’indirizzo di una struttura che laidentifichi.

La comunicazione tra i suddetti endpoint avviene secondo le già notemodalità specificate dalla “tripletta operativa”, costituita dai successivitre parametri dataGroup, dataArgumentType e messageId, ognu-no dei quali è semplicemente un codice specificato da un intero che inC\C++ il programmatore può impostare con l’aiuto di alcune costanti(qui riportate in enum).

L’ultimo campo dataPointer è un puntatore ad una struttu-ra che cambia a seconda degli attori e del tipo della comunicazione.Questa molteplicità di funzione viene esplicitata in dotNetTwain fa-cendo riferimento allo stesso codice con dieci diversi prototipi. Nel fi-le TwainNativeStubs.cs, la classe omonima TwainNativeStubracchiude

• la definizione di dieci delegati;

• dieci istanze di delegato (una per definizione);

• il codice per inizializzare dinamicamente tutte le istanze conriferimento ad una DLL.

Listing 4.2: Prototipi multipli della stessa funzione DSM_entry di TWAIN.

1 // DSM entry point DAT_ variants delegates:2 public delegate ReturnCode DSMparentDelegate ([In, Out

] TwainNativeTypes.Identity origin, IntPtr zeroptr,DataGroup dg, DataArgument dat, TwainMessage msg,

ref IntPtr refptr);3 public delegate ReturnCode DSMidentDelegate ([In, Out

] TwainNativeTypes.Identity origin, IntPtr zeroptr,DataGroup dg, DataArgument dat, TwainMessage msg, [In, Out] TwainNativeTypes.Identity idds);

Page 70: Tesi Todone

64 4. GEC_Scan

4 public delegate ReturnCode DSMstatusDelegate ([In, Out] TwainNativeTypes.Identity origin, IntPtr zeroptr,DataGroup dg, DataArgument dat, TwainMessage msg, [In, Out] TwainNativeTypes.Status dsmstat);

5 // DSM entry point DAT_ variants to DS:6 public delegate ReturnCode DSuserifDelegate ([In, Out

] TwainNativeTypes.Identity origin, [In, Out]TwainNativeTypes.Identity dest, DataGroup dg,DataArgument dat, TwainMessage msg,TwainNativeTypes.UserInterface guif);

7 public delegate ReturnCode DSeventDelegate ([In, Out] TwainNativeTypes.Identity origin, [In, Out]TwainNativeTypes.Identity dest, DataGroup dg,DataArgument dat, TwainMessage msg, refTwainNativeTypes.Event evt);

8 public delegate ReturnCode DSstatusDelegate ([In, Out] TwainNativeTypes.Identity origin, [In]TwainNativeTypes.Identity dest, DataGroup dg,DataArgument dat, TwainMessage msg, [In, Out]TwainNativeTypes.Status dsmstat);

9 public delegate ReturnCode DScapDelegate ([In, Out] TwainNativeTypes.Identity origin, [In]TwainNativeTypes.Identity dest, DataGroup dg,DataArgument dat, TwainMessage msg, [In, Out]TwainNativeTypes.Capability capa);

10 public delegate ReturnCode DSixferDelegate ([In, Out] TwainNativeTypes.Identity origin, [In]TwainNativeTypes.Identity dest, DataGroup dg,DataArgument dat, TwainMessage msg, ref IntPtrhbitmap);

11 public delegate ReturnCode DSpxferDelegate ([In, Out] TwainNativeTypes.Identity origin, [In]TwainNativeTypes.Identity dest, DataGroup dg,DataArgument dat, TwainMessage msg, [In, Out]TwainNativeTypes.PendingXfers pxfr);

12 public delegate ReturnCode DSiinfDelegate([In, Out]TwainNativeTypes.Identity origin, [In]TwainNativeTypes.Identity dest, DataGroup dg,DataArgument dat, TwainMessage msg, [In, Out]TwainNativeTypes.ImageInfo imginf);

Page 71: Tesi Todone

Tecnologie e tecniche implementative 65

Come si può vedere in 4.2 nella pagina 63, i prototipi sono simili, tut-ti accettano origine, destinazione e la tripletta operativa e restituisconoun codice di stato, ma differiscono principalmente per l’ultimo argomen-to, sempre un riferimento a un tipo complesso diverso di volta in volta(originariamente puntatore semplice).

Costruite delle funzioni richiamabili in C# secondo le consuetudinidi questo linguaggio, queste non sarebbero comunque utilizzabili senza ladefinizione di appropriati tipi. TWAIN adopera unicamente le su men-zionate costanti o tipi propri che mappano tipi primitivi (es. TW_UINT16è semplicemente ciò che in C si direbbe unsigned short int e che inC# è un System.UInt16) o record costruiti da essi, mentre la libreriadotNetTwain utilizza fondamentalmente tre categorie di tipi:

• enum che racchiudono i valori originariamente tenuti in costanti:questo permette una semplice enumerazione dei valori consentitianche a tempo di design (completamento automatico) e a tempodi esecuzione, consente un raggruppamento per area funzionale emigliora al contempo la leggibilità generale del codice; ogni co-stante originariamente utilizzata in più contesti è stata replicataall’interno di più tipi di enumerazione, corrispondenti ai vari casidi utilizzo;

• classi di collegamento: esse vengono usate per dialogare conTWAIN e costituiscono in pratica l’anello di congiunzione tramondo managed e mondo nativo;

• classi avanzate: sono classi totalmente gestite che incarnano le en-tità attrici delle varie operazioni TWAIN aggiungendo funzionalitàe rispetto delle consuetudini proprie dell’OOP.

Tutte le classi che mappano record semplici richiesti o restituiti daTWAIN sono contenuti nel file TwainNativeTypes.cs. È interes-sante analizzare più in dettaglio almeno una di queste classi (cfr. 4.3nella pagina 72).

La struttura è quella classica di una classe entità, che possiede deicampi, ma non particolari funzionalità se non quelle di base come con-versione a stringa e comparazione, più dei costruttori e una funzione dicopia.

Page 72: Tesi Todone

66 4. GEC_Scan

Ciò che è interessante notare, è che decorando la classe stessa e alcu-ni campi con appropriati attributi, il compilatore apprende esattamentecome vogliamo che la classe—pur restando managed—venga rappresen-tata in memoria, così da essere compatibile col codice di TWAIN che nonessendo cosciente di avere a che fare con una struttura gestita, tenta dipopolarla semplicemente scrivendo dati a prefissate locazioni di memoria;il parametro Pack nell’attribuzione di StructLayout, ad esempio, in-dica di allineare a 2 byte, mentre CharSet fornisce indicazioni sul cometrattare le stringhe.

I field Manufacturer, ProductFamily e ProductName hannobisogno di ulteriori specificazioni come la dimensione fissata a 34. Sepassata alla funzione DSM_Entry di TWAIN tramite uno dei delega-ti predisposti, questa classe verrà ispezionata dal codice nativo comese fosse un semplice record, con le caratteristiche impostate ed i campinell’ordine in cui sono stati definiti, mantenendo tuttavia dal lato dot-Net tutte le caratteristiche di una classe. Ciò permette di evitare lareplicazione delle strutture durante ogni comunicazione.

Il file TwainManagedClasses.cs contiene tutte le classi puramen-te managed prima definite “avanzate”; sono dedicate alla gestione ad altolivello delle comunicazioni con TWAIN, e sono tutte e sole le classi chemodellano i contenitori già descritti.

La gestione da parte di TWAIN di alcuni tipi come varianti ha crea-to non pochi problemi nel momento in cui invece nel codice dotNet sidesiderava considerare i contenitori come dei tipi generici.

Un ulteriore problema è che nello sviluppo del progetto si sarebbesentita la necessità di tenere delle liste di risultati di un’interrogazione,e quindi di liste eterogenee di contenitori con diversi tipi di dati.

Si è scelto di implementare un design per il quale:

• la classe ContainerBase contiene campi e funzionalità di baseper un contenitore, nonché del codice complesso che tramite re-flection e liste di funzioni di codifica e decodifica, è in grado diconvertire varianti in generici e viceversa;

• ogni contenitore specializzato è generico ma eredita dal tiponon generico ContainerBase, permettendo—ad esempio—diaggiungerne le istanze ad una List<ContainerBase>.

Page 73: Tesi Todone

Tecnologie e tecniche implementative 67

OneValue<T> Array<T> Range<T> Enumeration<T>

ContainerBase

Figura 4.10: Diagramma delle classi per i contenitori di TWAIN.

La classe principale di dotNetTwain è TwainWrapper; un’applica-zione che desideri utilizzare una periferica di acquisizione deve solo creareun oggetto di questo tipo ed utilizzarne le funzioni.

Durante la costruzione, TwainWrapper tenta di caricare il filetwain_32.dll (ma grazie al link dinamico, sarebbe possibile ancheutilizzare un file diverso) ed in caso di successo continua installando ungestore di messaggi ed effettuando un’enumerazione dei dispositivi otticipresenti: a questo punto, la logica dell’applicazione può esaminare la li-sta delle periferiche, sceglierne una ed effettuare subito un’acquisizione,oppure impostare alcune preferenze.

Esiste un metodo di TwainWrapper per ogni cambiamento di statoschematizzato nell’immagine 4.6 nella pagina 54; nonostante ciò, alcunetransizioni sono gestite automaticamente in maniera trasparente.

Ad esempio, una volta conclusa un’operazione di acquisizione, non cisi dovrà preoccupare di ripercorrere a ritroso la strada che ha portatoa tale stato finalizzando il DSM e la DS; in caso di chiusura dell’appli-cazione, DS e DSM verranno finalizzati automaticamente (liberando nelcontempo le eventuali corrispondenti risorse hardware).

Quando TWAIN si trova nello stato “transfer ready” (etichetta-to col numero 6 nell’immagine), TwainWrapper attende la ricezio-ne di un messaggio appropriato per effettuare un’ulteriore chiamata aDSM_Entry ed ottenere i dati relativi alle immagini acquisite; i dativengono ricomposti in una immagine gestita e viene sollevato un evento

Page 74: Tesi Todone

68 4. GEC_Scan

di avvenuta ricezione.Altri messaggi possono essere inviati tramite message pump per ge-

stire la fine della sessione di acquisizione, il reset forzato o altre evenienzepiù rare.

4.3.2 Grafica

In ambito dotNet, i componenti grafici comuni (EditBox, Label, Button,ecc. . . ) non sono disegnati da codice managed come invece accade soli-tamente in Java: ogni componente gestito fa semplicemente da wrapperal codice nativo corrispondente nelle API di Windows: se da un lato que-sto non consente una grande flessibilità o portabilità, dall’altro permetteuna certa rapidità di esecuzione, e quindi di una maggiore scorrevolezzadell’interfaccia grafica in generale.

Servendosi di molti componenti standard, quindi, gran parte dell’in-terfaccia utente di GEC_Scan si basa sull’ormai datato set di componen-ti WinForm; diversamente per il componente VisualSlideShow. Tramitei meccanismi di etichettatura e le collezioni in grado di sollevare even-ti in risposta ad una loro modifica, VisualSlideShow gestisce con logicainteramente dotNet il posizionamento delle icone di anteprima nella suaarea di disegno: dietro le scene, in maniera trasparente per lo sviluppa-tore, il disegno vero e proprio avviene—ancora una volta per questionidi prestazioni—tramite il collaudato GDI.

Questa commistione di tecniche vecchie e nuove, garantisce una buo-na risposta da parte dell’interfaccia, a patto di non caricarla troppo;essendo il cambio di contesto tra mondo managed e nativo piuttostodispendioso, si cerca di limitarlo al minimo.

Ad esempio, il clipping delle immagini completamente invisibili ègestito da codice dotNet, mentre nel caso complesso di un’immagineparzialmente visibile ci si affida a GDI per una corretta visualizzazione.

Anche a questo scopo, nell’oggetto di tipo DisplayInfo associato adogni immagine sono presenti

• indicazione sulla tipologia di immagine (per ora solo distinzione traimmagine utile e separatore);

• numero progressivo nella lista;

Page 75: Tesi Todone

Tecnologie e tecniche implementative 69

• posizione grafica nel visualizzatore;

• riferimenti ad eventuali finestre di ispezione aperte sull’immagine;

• eventuali eventi cui registrare un gestore per essere notificati dimodifiche nella struttura.

Un’icona viene disegnata solo se considerata la sua posizione e laposizione del viewport ciò viene ritenuto opportuno.

Ricordiamo che le icone sono immagini di dimensioni ridotte disegna-te per rendere l’idea delle sembianze di un’immagine ad alta risoluzione:per evitare di sovraccaricare il sistema ridimensionando al volo ogni im-magine ogni volta che ce ne sia il bisogno, è stata implementata unatecnica lazy : ogni volta che venga richiesta l’anteprima di un’immagineconservata, la si ricerca in una mappa che ha come chiavi le immagi-ni stesse, e come valori le versioni ridotte; solo se tale versione ridottanon viene trovata, si provvede a ricalcolarla. Ogni anteprima non vie-ne conservata per sempre, ma viene scartata dopo un certo tempo diinutilizzo.Listing 4.4: Estratto dalla classe TTTImageCollection: generazione al volo e

conservazione di una anteprima ridotta.

1 public Image getThumb(int index)2 {3 Image img = this[index].Item;4 Image generatedThumb = null;5 if (_thumbnails.ContainsKey(img))6 {7 generatedThumb = _thumbnails[img];8 }9 else

10 {11 generatedThumb = computeThumbnail(img);

_thumbnails.Add(img,generatedThumb);

12 }13 return generatedThumb;14 }

Le immagini a piena risoluzione vengono conservate non compresse.

Page 76: Tesi Todone

70 4. GEC_Scan

L’utilizzo intensivo della memoria non viene gestito esplicitamente,ma si assume che l’insieme di memoria fisica e virtuale della macchinadell’utente sia bastante a gestire le immagini raccolte; per verificare chenon vi fossero errori dovuti al codice in questo contesto critico, oltre agliunit test di base (condotti sulla maggior parte delle classi dell’intero pro-getto) è stato condotto un test di carico nel quale un processo di debugcreato ad hoc simulava per mille volte la pressione del tasto “Acquisisci”.Su un Pentium IV core-duo con 1 Gb di RAM, sistema operativo Win-dows XP SP3 con 3 Gb di memoria virtuale, selezionando come sorgentedati una fotocamera digitale che fornisce una foto per acquisizione, il testè terminato senza problemi acquisendo 1000 foto di dimensioni 640×480a 24 bit per pixel.

4.4 Installazione e preparazione dell’ambiente diesecuzione

Le macchine su cui i due programmi—software di controllo e softwaredi acquisizione—vengono eseguiti sono eventualmente coincidenti. Perquesto motivo si potrebbe essere portati a pensare che in tal caso lamaggior parte delle librerie utilizzate da entrambi i programmi possaessere condivisa evitando di replicare i file in ognuna delle rispettive car-telle di installazione. Per motivi tecnici legati anche all’utilizzo del CCW(3.3.8) questo non è possibile, e le cartelle dei due programmi devono ri-manere distinte, ognuna con la sua copia delle DLL; mentre nel caso delcontrollore le librerie vanno copiate tutte nella stessa cartella—e registra-te in ordine secondo la procedura descritta in 3.4 nella pagina 40—nelcaso del programma di acquisizione la struttura delle cartelle e la posi-zione dei file deve rimanere quella preordinata in fase di compilazione delprogetto, con la maggior parte delle librerie residenti nella stessa cartel-la dell’eseguibile principale insieme ad un file di configurazione ed unacartella plugins presente per contenere le estensioni ( 5.2 nella pagi-na 76); non sono richieste azioni di registrazione o simili, mentre restaun prerequisito l’installazione del dotNet runtime 2.0 o superiori.

La cartella plugins contiene file .dll, nei quali risiedono gli as-sembly dotNet relativi alle estensioni e ai tipi aggiuntivi: anche se il

Page 77: Tesi Todone

Installazione e preparazione dell’ambiente di esecuzione 71

codice che carica i plug in riesce a determinare se un assembly sia dacaricare o meno, è opportuno che nella cartella plugins ci siano solofile contenenti classi di estensione valide ed eventuali altri file ad essenecessari.

Il software di scansione documenti possiede un file di configurazione(chiamato al momento GECScan.CFG) che contiene molte impostazio-ni in formato XML; alcune di queste impostazioni sono accessibili dainterfaccia grafica, mentre altre riguardanti esigenze più inusuali sonoimpostabili solamente a mano nel file (es: funzioni di debug).

Il file di configurazione viene gestito in maniera intelligente: se duran-te l’esecuzione il programma dovesse rilevare modifiche nell’impostazionedelle preferenze, queste saranno poste in atto immediatamente (a menoche non si vada ad operare su caratteristiche che chiedono un riavvio).

Se il programma dovesse rilevare la cancellazione del file di configu-razione, ne ricreerà uno, ricostruendo—ad esempio—il percorso assolutodella sua cartella dei plug in ed impostando alcuni parametri ai lorovalori di default.

Per questo motivo, non è opportuno ridistribuire un file di configura-zione: è bene invece costruire al volo un file adeguato al sistema durantel’installazione, o lasciare che sia il software stesso a generarlo durantela prima esecuzione. I file .log presenti nelle cartelle ove alloggianoprogramma, plug in e oggetti COM contengono informazioni su erroriverificatisi durante l’esecuzione: per attivare il log impostare l’appositoparametro nel file di configurazione, ed eventualmente osservare il filecon appositi strumenti.

A fini di debug può risultare utile anche installare il driver virtualemesso a disposizione dal gruppo TWAIN2, che fornendo una immaginedi test alle richieste di acquisizione senza utilizzare alcun hardware puòaiutare a verificare il corretto comportamento del sistema.

2TWAIN sample data source http://www.twain.org/downloads.shtm.

Page 78: Tesi Todone

72 4. GEC_Scan

Listing 4.3: Riassunto della costituzione di una classe managed interfacciabile

con codice nativo tramite System.Runtime.InteropServices.Marshal.

1 [StructLayout(LayoutKind.Sequential, Pack = 2, CharSet =CharSet.Ansi)]

2 public class Identity // TW_IDENTITY3 {4 public IntPtr Id;5 public Version Version;6 public Int16 ProtocolMajor;7 public Int16 ProtocolMinor;8 public Int32 SupportedGroups;9

10 [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 34)]11 public string Manufacturer;12

13 [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 34)]14 public string ProductFamily;15

16 [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 34)]17 public string ProductName;18

19 public Identity() {...}20 public Identity(Identity src) {...}21 public Identity Clone() {...}22 public override string ToString() {...}23 public override int GetHashCode() {...}24 public override bool Equals(object obj) {...}25 }

Page 79: Tesi Todone

Capitolo 5Sottosistema diarchiviazione e plug in

5.1 Caratteristiche del sottosistema di archivia-zione

Il fine ultimo del sottosistema di archiviazione è quello di consentirela comunicazione tra GEC_Scan e un qualsiasi servizio di archiviazione.Questo servizio può essere locale, come un database sulla stessa macchinadi GEC_Scan e un servizio interno ad una rete locale, oppure remoto,come un servizio web pubblicato su Internet.

I requisiti fondamentali di tale sottosistema, evidenziati durante lafase di analisi toccano i seguenti temi:

• scalabilità;

• manutenibilità;

• trasparenza per l’utente finale;

• sicurezza;

• autenticazione.

73

Page 80: Tesi Todone

74 5. Sottosistema di archiviazione e plug in

Il sistema di archiviazione si basa sempre su servizi esterni: questo vuoldire che anche nel caso in cui venga utilizzato il servizio di archiviazionedi base—realizzato contestualmente al resto del progetto ( 5.3.1 nellapagina 84)—a questo si avrà accesso come ad un modulo distinto.

L’interfaccia con software o servizi web di terze parti non può esserestaticamente decisa a tempo di compilazione; tali servizi sono infattidiversificati e mutevoli, come diverse e mutevoli sono le tecnologie dautilizzare per usufruirne.

Per questo motivo il sottosistema di archiviazione di GEC_Scan nonpuò avere la forma di un codice monolitico, ma deve necessariamenteessere modulare e componibile per consentire di aggiungere, rimuovereo sostituire in qualsiasi momento il codice di comunicazione verso unqualsiasi servizio di archiviazione, sia esso locale o remoto.

Le metodologie di comunicazione tra GEC_Scan e un servizio di ar-chiviazione sono ovviamente dipendenti dal servizio e dalla tecnologia cheesso utilizza; nonostante questo, ci deve essere una base di funzionalitàaccessibili in maniera consistente dal resto del software GEC_Scan.

Parimenti, c’è la necessità che ogni funzionalità specifica di un certoservizio di archiviazione sia accessibile anche se sconosciuta a tempo dicompilazione di GEC_Scan; cioè: un modulo aggiuntivo di GEC_Scanpotrebbe venire istruito da GEC al fine di utilizzare correttamente unservizio che oltre alle funzionalità di base esporta anche funzioni estese,non note al momento del rilascio di GEC_Scan.

Un modulo rappresenta l’interfaccia tra GEC_Scan e un singolo ser-vizio: esso racchiude tutte e sole le funzionalità per tradurre il linguag-gio consistente di GEC_Scan nel linguaggio comprensibile dal servizioin esame (ad esempio una richiesta SOAP).

La creazione di un modulo deve risultare un’operazione semplice eche consenta di riutilizzare gran parte del codice già prodotto, di rapidosviluppo ed indipendente dal resto del codice di GEC_Scan: le com-plessità tecniche come l’interpretazione dei comandi e la gestione dellasoddisfazione di ogni singola richiesta risiederanno invece in un blocco dicodice comune e utilizzabile da tutti i moduli, in modo da semplificarele operazioni di creazione e manutenzione di ogni parte.

L’intero sottosistema di archiviazione dev’essere trasparente per l’u-tente finale, nel senso che a quest’ultimo devono essere nascosti tutti i

Page 81: Tesi Todone

Caratteristiche del sottosistema di archiviazione 75

meccanismi interni che gli permettono di effettuare le operazioni di ar-chiviazione; l’utente non partecipa mai esplicitamente alla selezione delservizio di archiviazione o alla configurazione del modulo corrispondente:tali istruzioni vengono impostate in GEC e spedite con la richiesta chedi volta in volta GEC invia a GEC_Scan.

Come le comunicazioni tra GEC e GEC_Scan sfruttano la sicurezzadel canale messo a disposizione da ASP, così la sicurezza di ogni comuni-cazione tra un modulo di archiviazione di GEC_Scan ed il corrispondenteservizio utilizzato sarà lasciato di volta in volta al canale trasmissivo.

Ad esempio, se si sta utilizzando un servizio web, si può decidere diutilizzare una comunicazione https; di norma le questioni di sicurezzadevono essere trattate in maniera assolutamente indipendente dal restodel codice.

Grande importanza riveste la questione dell’autenticazione, che inve-ce dev’essere gestita esplicitamente. Ogni utente deve poter archiviaredocumenti a suo nome, qualsiasi sia il servizio che GEC_Scan usa: ov-viamente l’utente dovrà essere stato preventivamente registrato pressoogni servizio di archiviazione usato durante le sessioni di acquisizione.

In aggiunta, determinati utenti devono poter essere delegati ad agireper conto di altri: si pensi al caso del commercialista che archivi ladocumentazione inerente ad un suo cliente.

Al di la degli obiettivi di scalabilità nei confronti di servizi non ancoraesistenti, una delle caratteristiche pratiche richieste al momento attualeè quella di poter salvare i documenti utilizzando due piattaforme moltopopolari: Microsoft Sharepoint e Google Documents.

5.1.1 Funzionalità di manipolazione file

Ogni modulo può implementare liberamente la connettività con un qual-siasi servizio, senza l’obbligo di dover sottostare a particolari vincoli;nonostante ciò, si è scelto di aggiungere un livello di astrazione tra iplug in e i servizi con cui si relazionano. Questo introduce dei requisitiaggiuntivi che riguardano le funzionalità minime di questo nuovo stratosoftware.

Sono richieste le medesime caratteristiche che di norma si ricercanoin un file system:

Page 82: Tesi Todone

76 5. Sottosistema di archiviazione e plug in

• esistenza di due tipi di oggetti: file e cartelle (o folder);

• funzionalità di enumerazione degli oggetti presenti in un folder;

• funzionalità di creazione di una cartella;

• funzionalità di upload del contenuto di un file;

• funzionalità di download del contenuto di un file;

• funzionalità di rimozione di un oggetto;

• funzionalità di aggiornamento del contenuto di un file.

Gli oggetti relativi a diversi provider, devono essere intercambiabili etrasparenti: si deve cioè poter operare su un qualsiasi documento conle medesime modalità pur ignorando il servizio sottostante al livello diastrazione.

5.2 Design del sottosistema di archiviazione

Per gestire i moduli in maniera indipendente dal codice principale si èscelto di organizzare il sottosistema di archiviazione come un plug in ma-nager, che può caricare e gestire ogni modulo di comunicazione chiamatoplug in.

Per architettura a plug in, si intende qualsiasi architettura softwareche permetta di ampliare le sue potenzialità con delle estensioni (chia-mate per l’appunto “plug in” o componenti aggiuntivi) che contengonocodice eseguibile, senza per questo richiedere la ricompilazione del soft-ware stesso. Ciò permette ad uno sviluppatore che non sappia come èfatto tale software, di scrivere del codice che vi si integri semplicementerispettando un’interfaccia concordata a priori.

Un plug in è un file contenente codice eseguibile che può essere ca-ricato, identificato ed eseguito dal manager in qualsiasi momento: ogniplug in viene concepito, sviluppato, compilato in un progetto a se stante.

Si è scelto di implementare ogni modulo in una singola classe cheerediti da una classe base (nella quale sono assolti i compiti comuni

Page 83: Tesi Todone

Design del sottosistema di archiviazione 77

come quelli inerenti la serializzazione): nel progetto questa classe è statachiamata ActionPerformer.

Ogni classe plug in estende ActionPerformer e ridefinisce un uni-co metodo di nome Perform, nel quale dovrà avvenire effettivamentel’archiviazione.

ActionPerformer—

+Perform

SomeActionPerformer—

+Perform

Figura 5.1: Per costituire un plug in riconosciuto, una classe deve ereditare

da ActionPerformer e Ridefinire Perform; ActionPerformer non è astratta e

il suo metodo Perform se richiamato lancia un’eccezione (le motivazioni sono

spiegate in 5.3 nella pagina 80).

Il plug in manager carica tutti gli assembly presenti in una cartella e,per ogni classe presente, verifica la discendenza da ActionPerformer.Un’altra parte del manager recupera dagli stessi assembly ogni tipo ag-giuntivo utilizzato dai performer riconoscendone la discendenza da alcunitipi fondamentali.

Nel corpo del metodo Perform di ogni performer risiedono le istru-zioni per il colloquio vero e proprio col servizio esterno: al suo internosi fa uso di classi e metodi che implementano la comunicazione, comead esempio chiamate a librerie, ad API, utilizzo di codice specifico perl’utilizzo di un certo servizio.

Nella filosofia della libreria di isolamento, ogni classe in grado di co-municare con un servizio qualsiasi implementa un’interfaccia discendente

Page 84: Tesi Todone

78 5. Sottosistema di archiviazione e plug in

IUserManager IDocumentManager ICalendarManager

IManager

Figura 5.2: Discendenza delle interfacce da IManager.

da IManager ; sono attualmente definiti tre tipi di gestori:

IDocumentManager fornisce i metodi per elencare, aggiungere, rimuo-vere, sostituire un documento su un servizio o una cartella/gruppodi documenti per i servizi che lo consentono;

IUserManager permette di amministrare gli utenti di altri servizi(come quello di archiviazione); permette di elencare, aggiungere,rimuovere utenti;

ICalendarManager esporta le funzionalità di base per accedere aservizi di tipo agenda, con funzioni per elencare, aggiungere,eliminare, aggiornare eventi in un calendario.

Ogni fornitore di servizio ha una classe base—anche astratta—cheimplementa IManager, e da cui derivano le classi che implementanoi vari servizi specifici; ad esempio, GoogleUserManager (implemen-tante IUserManager) e GoogleCalendarManager (implementanteICalendarManager) estendono la classe astratta GoogleManagerche a sua volta implementa IManager.

Page 85: Tesi Todone

Design del sottosistema di archiviazione 79

GoogleDocumentManager

IDocumentManager

GoogleUserManager

IUserManager

GoogleCalendarManager

ICalendarManager

GoogleManager

IManager

Figura 5.3: Diagramma delle classi per il fornitore di servizi Google; per com-

pattezza l’implementazione delle interfaccie viene schematizzata con il cerchio

in alto a sinistra (come in uso presso alcuni software) invece che con la freccia

tratteggiata (come da disposizioni UML).

Page 86: Tesi Todone

80 5. Sottosistema di archiviazione e plug in

I manager comunicano con i servizi che incapsulano utilizzando ingran parte le API messe a disposizione dai rispettivi fornitori, pre-via autenticazione. Per effettuare un’autenticazione è necessario unIAuthenticator: le classi che implementano questa interfaccia si oc-cupano di effettuare materialmente l’autenticazione quando necessario;ad esempio quello per SharePoint è MSAuthenticator.

Ogni manager opera su entità da lui gestibili: unGoogleDocumentManager non potrà accettare di eseguire ope-razioni su un oggetto che non sia stato creato da esso. Ogni servizioha le sue entità, ma le più comuni sono state dotate di un’interfacciastandard:

IUser con informazioni di username e password;

IDocument permette l’accesso a dati come nome originario del file,rappresentazione binaria del file, ecc. . .

ICalendarEvent esporta proprietà di inizio e fine dell’evento,descrizione, proprietario, ecc. . .

implementate poi dalle classi GoogleUser, SharePointUser,GoogleDocument, SharePointDocument, e così via.

5.3 Specifiche e tecnologie

Prima dell’avvento dei contesti di programmazione gestiti e quindi dellareflection (ovvero della capacità di ispezionare codice eseguibile e tipi arun time), un plug in era semplicemente una DLL nativa che esporta-va delle funzioni di nome noto a priori; un’applicazione che intendesseavvalersene necessitava solo di caricare dinamicamente la libreria e dichiamare la funzione desiderata.

Essendo maturato il progetto in un contesto come dotNet che per-mette di caricare ed ispezionare codice e tipi complessi non noti a tempodi compilazione, è possibile trarre addizionale vantaggio da ereditarietà epolimorfismo e si è perciò scelto di implementare l’architettura estensibilefacendo in modo che:

Page 87: Tesi Todone

Specifiche e tecnologie 81

• ogni componente aggiuntivo sia una classe che implementa unacerta interfaccia o che eredita da una certa classe base;

• molte classi (e quindi molti plug in) possano risiedere in uno stessoassembly;

• non ci sia limite al numero di assembly (e quindi di plug in)caricabili e utilizzabili dal programma host.

Si è scelto di non scrivere del codice specifico per il tipo di plug in cheviene usato dal programma di acquisizione, ma di creare una piccolalibreria riutilizzabile di funzioni che aiutino a creare il proprio siste-ma modulare caso per caso. Due classi chiamate PluginsManagere RuntimeTypeManager forniscono una serie di funzioni per:

• caricare una certa classe;

• caricare tutte le classi di un certo assembly che implementino unacerta interfaccia o ereditino da una certa classe base;

• caricare tutte le classi di tutti gli assembly di una cartella cheimplementino una certa interfaccia o ereditino da una certa classebase.

È possibile usare una delle due classi a seconda delle proprie esigenze:PluginsManager accetta come parametro generico il tipo di base chedeve esser quindi noto a tempo di compilazione e resta tale per tutta lavita di ogni istanza. Ad esempio potremmo volere che ogni nostra esten-sione sia una classe specializzata che eredita da PluginBase: potremmoistanziare

1 PluginManager<PluginBase> myManager = new PluginManager<PluginBase>();

e poi fargli caricare da una cartella tutte le classi che ereditano daPluginBase con

1 myManager.loadFromDirectory(path, filter);

Page 88: Tesi Todone

82 5. Sottosistema di archiviazione e plug in

dove filter è l’estensione dei file che possono contenere gliassembly.

RuntimeTypesManager permette di caricare classi che implemen-tino almeno un’interfaccia presente tra una lista di tipi proposti o de-rivino da una classe base presente tra una lista di tipi proposti; questopuò essere utile nel caso ci sia la necessità di gestire a run time dei tipiutilizzati soltanto nel codice non noto a tempo di compilazione (ad esem-pio nel progetto ciò è utile ai fini della serializzazione). Si può istanziareun RuntimeTypesManager e fargli caricare i tipi desiderati da unacartella con

1 RuntimeTypesManager myTypeManager = new

RuntimeTypesManager();2 myTypeManager.loadFromDirectory(path, filter, types);

dove types è una collezione di tipi (interfacce o classi base) chepermette di individuare i tipi caricare.

Il programma di acquisizione utilizza le funzioni messe a disposizionedalle classi viste per caricare dinamicamente dei plug in di esportazione;essi vengono chiamati ActionPerformer, come la classe base da cuidiscendono.

Listing 5.1: Interfaccia di un ActionPerformer, classe base di un plug in.

1 public class ActionPerformer : IXmlSerializable2 {3 public ActionPerformer();4 public string Name { get; }5 public XmlSchema GetSchema();6 public bool IsFaking();7 public virtual ActionResponse Perform(BaseSync

syncObject, JobId job, int groupId, DocInfoadditionalData, ActionRequest actionRequest, IList<ITaggedItem<Image, Page>> images);

8 public void ReadXml(XmlReader reader);9 public void WriteXml(XmlWriter writer);

10 }

Page 89: Tesi Todone

Specifiche e tecnologie 83

Metodi e proprietà sono tutti implementati nella classe base; granparte del codice serve a gestire la serializzazione. Questa avviene sempli-cemente trasmettendo il nome dell’ActionPerformer: se il codice chedeserializza lo conosce (cioè se ha caricato grazie a PluginManager unaclasse derivata da ActionPerformer il cui nome è quello specificato)provvede ad istanziarlo, altrimenti solleva un errore.

XmlSchema è presente per poter implementare l’interfacciaIXmlSerializable ma non è utilizzato e torna null;

WriteXml scrive nel flusso di serializzazione l’attributo namecontenente la stringa recuperata da un campo privato _name;

ReadXml scrive nel campo privato _name quanto recuperato dall’attri-buto name nello stream di serializzazione in input;

IsFaking permette di verificare se l’oggetto su cui è invocato è la cor-retta istanza della classe derivata da ActionPerfomer o se inveceè istanza della classe base, appena deserializzata e di cui dobbiamoconsiderare solo il nome (cioè: chiamare Perform genererebbe unerrore);

Name è proprietà che pubblica il campo privato _name, inizializzatoal nome della classe nel costruttore ed eventualmente ridefinito indeserializzazione;

Perform solleva semplicemente un’eccezioneNotSupportedException; è cura della classe derivata ridefinirePerform in modo che compia le azioni desiderate.

A Perform vengono passati:

• un riferimento all’oggetto di sincronia che gestisce le comunicazioni;

• il JobId del lavoro che sta venendo soddisfatto;

• un numero che indica il progressivo del documento processato (puòservire per la nomenclatura dei file);

• dei meta dati relativi al documento processato;

Page 90: Tesi Todone

84 5. Sottosistema di archiviazione e plug in

• un riferimento alla richiesta originaria che ha scatenato il processodi lavoro;

• la lista ordinata delle immagini acquisite durante la sessione(eventualmente etichettate con informazioni aggiuntive).

Ciò che si ottiene indietro dal plug in è un oggetto di tipoActionResponse che contiene il dettaglio delle operazioni effettua-te con la chiamata a Perform (andrà poi inclusa in una Response efatta pervenire a GEC).

5.3.1 Archiviazione locale e debug

SaveToFileActionPerformer e TestActionPerformer (di de-bug), fanno parte di un pacchetto di nome BasicPlugins. Essi nonhanno nessun vantaggio rispetto ad altri plug in, ma sono consideraticapacità che un’istanza del programma di scansione non può non avere.

Il primo salva i dati in una cartella specificata, mentre il secon-do fa semplicemente comparire una finestra di dialogo modale (recan-te l’informazione che si tratta di un test) all’utente del programma discansione. Ogni Performer si avvale di tipi specializzati derivanti daActionRequest, ActionResponse, ResponsePage. Nel caso diSaveToFileActionPerformer, questi sono:

SaveToFileActionRequest : trasporta dal fruitore al fornitore delservizio indicazioni su percorso della cartella in cui vanno salvati idati e formato richiesto. Il formato è indicato con un enum pre-definito noto al resto dell’applicazione, che viene comunicato sottoforma di stringa nei file di comunicazione; il campo Performerereditato da ActionRequest viene impostato automaticamentea SaveToFileActionPerformer;

SaveToFileActionResponse: trasporta dal fornitore al fruitore delservizio indicazioni sulla cartella in cui i dati sono stati effettiva-mente salvati; ereditando da ActionResponse, possiede una listadi ResponsePage cui vanno aggiunti degli oggetti di tipo FSPagee una lista di Error; a quest’ultima possono essere aggiunti oggettirappresentanti errori di tipo base o specializzato;

Page 91: Tesi Todone

Specifiche e tecnologie 85

FSPage: eredita da ResponsePage, per cui contiene un identificativoche indica la Page a cui si riferisce; contiene inoltre il percorso e ilnome del file contenente i dati per questa pagina in questa azione.

SaveToFileActionPerformer può essere usato per salvare una copia deidocumenti acquisiti il locale (ovvero su un qualsiasi file system visibiledal GEC_Scan che esegue il plug in) anche in combinazione con altritipi di archiviazione remota.

5.3.2 Funzionalità estese ed archiviazione Remota

Le funzionalità più utili e complesse del sottosistema di archiviazionesono quelle relative all’integrazione con servizi remoti di terze parti.

Come prova di fattibilità ci si è cimentati a realizzare delle strutturedi interfaccia con i servizi di archiviazione ed organizzazione di Micro-soft Sharepoint e Google Apps: insieme essi costituiscono uno spaccatorappresentativo di questo tipo di servizi, funzionando entrambi con lacollaudata tecnologia dei web server, seppur ognuno con diversa filosofia.

La libreria di interfaccia prodotta isola l’utilizzatore dai dettagli im-plementativi dei due sistemi, e permette di appoggiarsi a questi serviziin maniera consistente per l’utilizzo dei servizi di gestione documenti ecalendario.

Allo stato attuale delle cose, le possibilità aperte dalla combinazionedi questa libreria di interfaccia col resto del sistema di acquisizione edarchiviazione sono ancora in fase di studio per una applicazione praticain produzione.

Le funzioni complesse implementabili a partire dalle primitive fornitevanno dalla condivisione di documenti a vario titolo tra ditte e clienti,alla sincronia tra file system, dal back-up di dati, all’organizzazione deiflussi di lavoro/approvazione in una realtà aziendale. Con la gestionedei servizi relativi a calendario ed appuntamenti, è stata resa possibilela creazione automatica di note ed eventi.

Per avere un’idea di cosa è possibile fare e come, seguono le descri-zioni dei due servizi menzionati, e degli argomenti tecnici affrontati perpoterne fare un uso proficuo.

Page 92: Tesi Todone

86 5. Sottosistema di archiviazione e plug in

5.3.2.1 Sharepoint

SharePoint è un prodotto di Microsoft originariamente nato come serverper la nota suite Office; la sua funzionalità iniziale era quella di fareda repository per i documenti prodotti con gli strumenti Microsoft, masi è oggi estesa ad un gran numero di possibilità. Uno degli sviluppipiù evidenti di SharePoint è stato quello nel miglioramento continuodell’interfaccia basata sul web, tanto che molte realtà aziendali anche adalto livello1, lo utilizzano per creare siti dedicati al proprio pubblico.

Le sue funzionalità di gestione includono la possibilità di accettare deifile e di sottometterli ad un processo di revisione/accettazione completa-mente personalizzabile, la possibilità di gestire la redazione collaborativae molte versioni di ogni documento, la possibilità di associare dei metadati ad ogni singolo file e l’opportunità di gestire gruppi di utenti condiversi diritti di elenco/lettura/scrittura/approvazione.

La versione utilizzata durante lo sviluppo è SharePoint 2007, incui è presente una massiccia integrazione con la tecnologia dotNet. Imetodi di dialogo e sottomissione documenti con questa versione sonofondamentalmente due:

• utilizzando i servizi di base già esportati tramite web servicepredefiniti;

• scrivendo un’estensione dotNet per SharePoint che dialoghi colmondo esterno come ritiene più opportuno.

Si è scelto di seguire la prima strada per diversi motivi:

• mantenere un pezzo di codice è più facile, immediato, economicoche mantenerne due;

• nei casi di utilizzo reale, quasi sempre SharePoint sarà installato suuna macchina di terza parte e pertanto non configurabile al livellorichiesto per installare funzionalità aggiuntive;

• la comunicazione tramite web service è un’operazione ormai diffusae facilmente integrabile anche con sistemi complessi.

1Nei sorgenti delle pagine di http://www.ferrari.com ad esempio, è possibileleggere <meta name="GENERATOR" content="Microsoft SharePoint" />.

Page 93: Tesi Todone

Specifiche e tecnologie 87

Le funzionalità di SharePoint sono accessibili—previa autenticazione—dal web tramite servizi SOAP2 (tutti accessibili all’indirizzo http://server/_vti_bin/ o http://server/site/_vti_bin/; dove“server” è il nome del server e “site” l’url relativo di un sito Sharepoint):

nome servizio descrizioneAdmin.asmx metodi amministrativi, come quelli per

creare o eliminare sitiAlerts.asmx metodi per lavorare con gli alert

DspSts.asmx metodi per recuperare schemiDWS.asmx metodi per lavorare con i Document

WorkspaceForms.asmx metodi per gestire le interfacce utente

di tipo FormImaging.asmx metodi per gestire immagini

Lists.asmx funzioni di gestione delle listeMeetings.asmx metodi per lavorare sui Meeting

WorkspacePermissions.asmx metodi per lavorare con SharePoint

Services securitySiteData.asmx metodi esportati per Windows

SharePoint Portal ServerSites.asmx contiene un singolo metodo per

ottenere template di sitiUserGroup.asmx metodi per lavorare con utenti e

gruppi3versions.asmx consente di lavorare con il versioning

dei fileViews.asmx permette di gestire le viste associabili

alle listeWebPartPages.asmx gestisce le WebPart4

Webs.asmx consente di gestire (non amministrare)siti e sotto siti

2Qualcuno sta tentando di mettere insieme delle funzioni per accedere a Share-Point anche tramite interfaccia di tipo REST http://www.codeplex.com/REST4SharePoint.

Page 94: Tesi Todone

88 5. Sottosistema di archiviazione e plug in

Come si può notare dai molti riferimenti nella lista dei servizi di-sponibili, gli utenti di SharePoint hanno come punto di riferimento un“sito” con significato non dissimile da quello del classico sito web; perorganizzare i documenti è necessario (tramite l’interfaccia web di Share-Point Server) configurare un sito SharePoint, permetterne l’accesso adeterminati utenti e predisporre una lista.

Le liste di documenti—che nelle ultime versioni di SharePoint hannosoppiantato i Document Workspace—sono in realtà liste di veri e pro-pri tipi (definibili nell’area di amministrazione) che possono usufruireaddirittura di una forma rudimentale di ereditarietà: per l’utilizzo colsoftware di archiviazione proposto, bisogna quindi creare anche un tipoche specifichi il tipo file sottomesso con dei campi atti a contenere i metadati.

I servizi utilizzati nel software prodotto sono principalmente Lists eWebs. Il primo per effettuare l’enumerazione di una lista, il secondo perricavare alcuni URL necessari nell’utilizzo del primo servizio (sono a voltenecessarie conversioni da stringhe di identificazione a nomi o viceversa).

Per inviare un file, è sufficiente fare un semplice http PUT ad un benpreciso indirizzo corrispondente ad una lista, eventualmente modificatoper aggiungere un percorso di cartelle interne alla lista; per associare deimeta dati, si opera successivamente sul file già caricato con i metodi diLists.

Per ricevere informazioni su un tipo, una lista o un sito, i servizi diSharePoint utilizzano un linguaggio di query basato su XML chiamatoCAML5 del quale si è utilizzata solo una piccola parte, senza scriverecodice generico o specifico di funzionalità che non si intendesse usare.

I calendari per Sharepoint sono semplicemente liste specializzate, chegodono di un’interfaccia grafica dedicata, e pertanto vengono gestitein modo analogo a tutte le altre liste, comprese quelle utilizzate perimmagazzinare documenti.

Le richieste vengono materialmente costruite grazie alle classi gene-rate dal wizard per webserver di Visual Studio 2008: il loro utilizzo causal’inizio di un colloquio SOAP come quello visibile nel listato 5.3.

5Collaborative Application Markup Language; esempi in [7].

Page 95: Tesi Todone

Specifiche e tecnologie 89

Listing 5.2: Esempio di codice CAML per l’update di due campi in un

determinato oggetto.

1 <Batch OnError="Continue">2 <Method ID="1" Cmd="Update">3 <Field Name="ID"></Field>4 <Field Name="field1">value1</Field>5 <Field Name="field2">value2</Field>6 </Method>7 </Batch>

Listing 5.3: Esempio di richiesta e risposta al server Sharepoint dal punto

di vista http: il client con l’azione POST dichiara l’intenzione di effettuare

una richiesta SOAP (si noti l’intestazione SOAPAction) ed attende un codice

100 dal server; all’arrivo di questo, il client provvede ad allegare nel corpo della

richiesta codice XML che specifica la query (in questo caso l’enumerazione degli

oggetti contenuti in un folder della lista il cui identificativo univoco è specificato

nell’elemento listName). La risposta ottenuta è 200 OK e nel corpo, codice

XML che rappresenta l’insieme degli oggetti restituiti dalla query (omesso per

brevità). Si sono omesse le fasi di autenticazione.

1 (il client invia)2 POST /ScanTodRepo/_vti_bin/Lists.asmx HTTP/1.13 User-Agent: Mozilla/4.04 Content-Type: text/xml;5 charset=utf-86 SOAPAction: "http://schemas.microsoft.com/sharepoint/

soap/GetListItems"7 Authorization: Basic U0hQVF9UZXN0VXNlcjE6c2hhcGU=8 Host: mida-shpt19 Content-Length: 605

10 Expect: 100-Continue11

12 (il server invia)13 HTTP/1.1 100 Continue14

15 (il client invia)16 <?xml version="1.0" encoding="utf-8"?>17 <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/

soap/envelope/" xmlns:xsi="http://www.w3.org/2001/

Page 96: Tesi Todone

90 5. Sottosistema di archiviazione e plug in

XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">

18 <soap:Body>19 <GetListItems xmlns="http://schemas.microsoft.com/

sharepoint/soap/">20 <listName>{F19B0826-253B-4C12-B2AE-585C4CDA3913}</

listName>21 <viewName />22 <rowLimit />23 <queryOptions>24 <QueryOptions xmlns="">25 <Folder>repository 1</Folder>26 <DateInUtc>false</DateInUtc>27 <IncludeMandatoryColumns>true</

IncludeMandatoryColumns>28 </QueryOptions>29 </queryOptions>30 </GetListItems>31 </soap:Body>32 </soap:Envelope>33

34 (il server invia)35 HTTP/1.1 200 OK36 Date: Tue, 10 Nov 2009 11:56:4237 GMTServer: Microsoft-IIS/6.038 X-Powered-By: ASP.NET39 MicrosoftSharePointTeamServices: 12.0.0.451840 X-AspNet-Version: 2.0.5072741 Set-Cookie: WSS_KeepSessionAuthenticated=80; path=/Set-

Cookie: MSOWebPartPage_AnonymousAccessCookie=80;expires=Tue, 10-Nov-2009 12:26:42 GMT; path=/Cache-Control: private, max-age=0Content-Type: text/xml;charset=utf-8Content-Length: 5824Ogn

In Sharepoint i nomi assegnati agli oggetti non necessitano di essereunici, nemmeno internamente ad uno stesso contesto (es: due file nellastessa cartella, due oggetti nella stessa lista); ogni oggetto può essereindirizzato tramite:

fileRef, un URL che fa riferimento al file che lo rappresenta;

Page 97: Tesi Todone

Specifiche e tecnologie 91

UniqueId, un identificativo univoco per tutto il server Sharepoint(purtroppo scarsamente supportato nelle interfacce web);

la coppia composta dall’identificativo univoco della lista contenitore el’ID, un numero intero progressivo assegnato a ciascun oggetto diogni lista, univoco solo all’interno di tale lista.

Listing 5.4: Prototipi delle funzioni GetListItems e UpdateListItems create

dal generatore automatico di Visual Studio 2008 per accedere alle omonime

funzioni esportate dal servizio web Lists.asmx.

1 public XmlNode GetListItems(string listName, stringviewName, XmlNode query, XmlNode viewFields, stringrowLimit, XmlNode queryOptions, string webID)

2

3 public XmlNode UpdateListItems(string listName, XmlNodeupdates)

Le azioni di base di enumerazione, creazione, cancellazione sono ot-tenute manipolando nomi, url, ID e identificativi univoci ed utilizzan-doli in congiunzione con i due metodi web esportati da Lists.asmx:GetListItems e UpdateListItems.

Esse sono implementate nel seguente modo:

Enumerazione: viene effettuata chiamando il metodo webGetListItems, specificando l’identificativo univoco dellalista che si va ad enumerare, nessuna query ed eventualmentespecificando il nome del folder da enumerare all’interno dellastruttura queryOptions; la risposta contiene del codice XMLorganizzato come entità contenute in elementi z:row contenuti aloro volta in un elemento rs:data;

Creazione di una cartella: viene effettuata tramite chiamata al meto-do web UpdateListItems, specificando l’identificativo univoco dellalista su cui si va ad operare ed una query CAML contenente no-me della nuova cartella ed eventualmente la sua posizione nellastruttura delle cartelle già esistenti;

Page 98: Tesi Todone

92 5. Sottosistema di archiviazione e plug in

Cancellazione di un oggetto (file o cartella): effettuato tramite Up-dateListItems e una query di cancellazione che fa riferimentoall’oggetto da cancellare tramite il suo indirizzo URL;

Download: fatto semplicemente tramite una http GET autenticata al-l’indirizzo URL di un oggetto, restituisce nel corpo della rispostail contenuto binario del file;

Upload e aggiornamento del contenuto: ottenuti con un http PUT au-tenticato all’URL costruito dall’URL della cartella concatenato colnome che si vuole assegnare al file; restituisce l’URL del file nelleintestazioni della risposta in caso di successo.

In Sharepoint ogni utente registrato al servizio dev’essere un utente didominio o della macchina su cui è in esecuzione il server; l’autentica-zione avviene quindi a livello http con il consueto meccanismo Basic oNTLM per cui occorrono uno username ed una password, eventualmentecorredati dal nome del dominio per cui essi valgono.

Nel codice dotNet l’autenticazione avviene in modo trasparente tra-mite l’oggetto System.Net.NetworkCredential che implemental’interfaccia ICredentials: tutte le richieste inviate al server Share-point vengono preparate in modo da utilizzare le credenziali fornite contale oggetto, senza che sia visibile il meccanismo di autenticazione veroe proprio.

Situazioni di necessità di una delega ad operare sui dati di un’al-tro utente vengono gestite grazie al complesso pannello di controllo chepermette di stabilire i permessi di ogni utente con grana piuttosto fine.

5.3.2.2 Google Documents

Google Documents è un pacchetto di servizi basati su un’interfaccia uten-te web che racchiude le funzionalità di word processing, foglio di calco-lo, calendario appuntamenti e presentazione. Nato nel 2006 in seguitoall’acquisizione da parte di Google di Upstartle e di XL2Web (autoririspettivamente delle versioni originarie di quelli che oggi sono il wordprocessor “writely” e il foglio elettronico) oggi il sistema gode della pre-senza di molte caratteristiche desiderabili, come ad esempio la possibilitàdi interfaccia tramite web service.

Page 99: Tesi Todone

Specifiche e tecnologie 93

Il fatto di essere un insieme di servizi mantenuto da Google—e non unsoftware—lo rende ideale per un immediato utilizzo a causa dell’assenzadi installazione, delle minime richieste di manutenzione e dell’assenzaper l’utente di problematiche inerenti l’integrità dei dati o la sicurezza(che vengono ovviamente coperte dal proprietario).

L’intero protocollo di interfaccia ad ogni funzionalità di Google sibasa su REST6, ed in particolare su delle estensioni di ATOM7 chiamateAPP8 che permettono la pubblicazione e la gestione di risorse condivisesul web.

Nonostante negli intenti degli sviluppatori i servizi avrebbero dovu-to essere fruibili utilizzando solo funzioni di alto livello (le cosiddette“Google Data API” [4]), non tutte le funzioni vengono implementate inmaniera soddisfacente nel kit di sviluppo per dotNet e si è provvedutoquindi a scrivere del codice che in alcune parti si interfaccia con i serviziGoogle ad un livello più basso.

L’ultima versione delle API9 è la 3.0, ma per il progetto in esame èstata comprensibilmente usata l’ultima stabile, la 2.0.

Il fatto che protocollo ed API siano un prodotto giovane, in rapidaevoluzione e non del tutto documentato, ha introdotto notevoli difficoltànel raggiungimento degli obiettivi minimi di manipolazione dei dati; ilsistema possiede numerosi difetti tra i quali l’impossibilità di enumera-re gli oggetti che risiedono nella cartella principale (cioè che non sonoall’interno di alcuna cartella), l’impossibilità di gestire richieste tropporavvicinate nel tempo10 e la grande latenza tra il momento in cui si crea

6REpresentational State Transfer; filosofia di costruzione servizi web che utilizzarichieste codificate direttamente nella richiesta HTTP e la risposta come contenutoin formato XML.

7Il nome non ha un’origine chiara; specifiche in [2].8Atom Publish Protocol; specifiche in [1].9API o Application Program Interface(s); c’è talvolta ambiguità sull’utilizzo del

termine: in alcuni casi sta ad indicare in maniera astratta l’insieme di convenzioni dicomunicazione da adottare verso una certa tecnologia, mentre a volte nell’uso comuneesso vuole riferirsi al codice che materialmente permette di accedere a determinatefunzionalità. Diciamo in questa sede “protocollo” l’insieme delle convenzioni di comu-nicazione tra un client e i servizi di Google, mentre definiamo “API” il codice fornitoda Google che implementa tale protocollo.

10Google dichiara che la rapidità massima è di 5 query al secondo, masperimentalmente questo numero cala ulteriormente.

Page 100: Tesi Todone

94 5. Sottosistema di archiviazione e plug in

un oggetto e il momento in cui diventa possibile recuperarlo.Si è cercato di ovviare queste ed altre problematiche utilizzando di

volta in volta le API per dotNet o funzioni implementate da zero aseconda delle necessità.

Le richieste, a prescindere dal codice che le ha originate, si presentanocome http PUT, GET, POST, DELETE.

Listing 5.5: Esempio di una richiesta di enumerazione documenti effettuata

tramite http GET all’indirizzo del feed dei documenti; i documenti restituiti

dipendono dall’utente autenticato, e vengono forniti nel corpo della risposta

come codice XML nella forma di un AtomFeed contenente delle AtomEntry.

Questa richiesta restituisce tutti i documenti a prescindere dalla loro ubicazione

nella struttura delle cartelle: i risultati vanno quindi filtrati sul client. Per

recuperare solo il contenuto di una certa cartella si effettua la stessa richiesta

all’indirizzo del feed di quella cartella. La cartella di root non possiede feed.

1 GET /feeds/documents/private/full?showfolders=true HTTP/1.1

2 Content-Type: application/atom+xml;3 charset=UTF-84 User-Agent: G-Mida4Worker/GDataGAuthRequestFactory-CS-

Version=1.4.0.25 Authorization: GoogleLogin auth=DQAAAIcAAABFjdyD6oB...6 GData-Version: 2.07 Host: docs.google.com8

9 HTTP/1.1 200 OK10 ...

Anche nell’ambiente dei servizi Google un oggetto non necessita dipossedere un nome univoco: per riferirsi ad un oggetto preciso è neces-sario indicare uno dei suoi indirizzi URL (solitamente quello chiamato“EditUrl”); questo è a sua volta composto dall’URL del feed per gli og-getti di un certo tipo (esistono diversi feed per documenti, cartelle, eventidel calendario ecc. . . ) seguito da una lunga stringa che costituisce unidentificativo univoco per quel feed.

Le funzionalità di base per la manipolazione di cartelle e file, dipen-dono da un oggetto di tipo DocumentService—che si cura tra le altrecose dell’autenticazione—e sono state ottenute nel seguente modo:

Page 101: Tesi Todone

Specifiche e tecnologie 95

Enumerazione: si costruisce un oggetto DocumentsFeedQuery—messo a disposizione dalle API—e si provvede eventualmente adaggiungere dei dettagli sulle modalità desiderate dell’enumerazione(es: la cartella da enumerare, opzioni sulla ricorsione, . . . ) trami-te la classe AtomCategory; si effettua la richiesta vera e propriapassando l’oggetto DocumentsFeedQuery così creato al metodoDocumentService.Query(); questo restituisce una collezionedi DocumentEntry, contenente i dati richiesti sugli oggetti inte-ressati dalla query; nel protocollo versione 2.0 l’enumerazione diuna cartella avviene specificando il nome e non l’identificativo uni-voco, perciò in caso di cartelle omonime, ci si può attendere qualcheinesattezza;

Creazione di una cartella: si crea un oggetto AtomEntry il cui ti-tolo viene impostato al nome da assegnare alla nuova cartella, ela cui categoria viene impostata a FOLDER_CATEGORY; si utilizzaDocumentService.EntrySend() per effettuare materialmentela richiesta di creazione verso un certo URL: /feeds/folders/private/full/folder%3Afolder_id (dove folder_id èuna stringa che funge da identificativo univoco della cartellacontenitore) se si intende creare una sottocartella, /feeds/documents/private/full/folder se si desidera creare unacartella in root; non è possibile recuperare un oggetto cartellaimmediatamente dopo la sua creazione;

Cancellazione di un oggetto (file o cartella): effettuato chiamando ilmetodo Delete() che ciascun DocumentEntry possiede; questocausa l’invio di una http DELETE all’indirizzo chiamato editUridel DocumentEntry;

Download: fatta semplicemente tramite una http GET autenti-cata all’indirizzo di un oggetto, eventualmente accodando&exportFormat=format per specificare il formato in cui si vuo-le convertire il file: non è possibile risalire al formato originario delfile caricato, e si è quindi creato un sistema di formati di default percaricare/scaricare le varie tipologie di documento (testo, presenta-

Page 102: Tesi Todone

96 5. Sottosistema di archiviazione e plug in

zione, foglio di calcolo, pdf); restituisce nel corpo della risposta ilcontenuto binario del file;

Upload e aggiornamento del contenuto: ottenuti tramite chiamataa DocumentService.Insert(); l’indirizzo passato al metodo(che corrisponde all’indirizzo al quale verrà effettuato l’http POST)si calcola con riflessioni analoghe al caso della creazione folder.

Listing 5.6: Esempi di richieste http originate dalle chiamate alle funzioni

delle API per i documenti di Google; nell’ordine: creazione di una cartella di

nome “testFldr3”, cancellazione di una cartella dato il suo identificativo univoco

e caricamento di un file.

1 POST /feeds/documents/private/full2 ...3 <entry xmlns="http://www.w3.org/2005/Atom"> <title type

="text">testFldr3</title> <category term="http://schemas.google.com/docs/2007#folder" scheme="http://schemas.google.com/g/2005#kind" /></entry>

4

5 DELETE /feeds/documents/private/full/folder%3A0B96YFnY2kRSbMjJkND...

6

7 POST /feeds/documents/private/full8 Slug: New Rich Text Document9 Location: http://docs.google.com/feeds/documents/private

/full/document%3A0Ad6YFnY2kRSbZGhtbTVqbnBfNmoyd2I5N2R2

10 (contenuto)

Sebbene a tutt’oggi i servizi di Google si siano evoluti introducendo ilconcetto di cartelle condivise, nel momento della prima stesura del codicee di questo testo, il sistema di account non permetteva la condivisionedi un intero spazio di lavoro, nè di stabilire una gerarchia tra utenti consuddivisione dettagliata dei privilegi; se si pensa a questo in termini dicasi di utilizzo, è facile immaginare che per condividere documenti e spazidi lavoro, fosse necessario un sistema di delega.

Tale sistema di delega viene implementato con il sistema di autenti-cazione chiamato “OAuth 2-legged authentication”. Quando si parla di

Page 103: Tesi Todone

Setup dei sistemi di archiviazione 97

OAuth, di solito ci si riferisce ad un sistema di autenticazione chiama-to “3-legged authentication” nel quale si compie una cosiddetta “danza”nella quale l’utente che voglia consentire al sito B accesso ai suoi datipresso il sito A, si vede ridirezionato (anche dal punto di vista grafico)varie volte tra i due siti.

Nel nostro caso invece si fa uso della cosiddetta “2-legged authentica-tion” (chiamata ai primordi anche “Signed Fetch” o “Phone Home”) checonsente l’autenticazione per delega senza la danza descritta.

Il sistema si basa sulla condivisione di un segreto tra delegato e de-legante, per cui il delegato non necessita di possedere le credenziali diaccesso del delegante, mantenendo il diritto ad accedere ai suoi dati anchenel momento in cui il delegante cambiasse password.

Tale sistema richiede una sorta di firma dei parametri di ogni richiestae un token di autorizzazione ottenuto da nome utente delegato, chiavecosiddetta “consumer key” e chiave cosiddetta “consumer secret”.

Tutti i dati necessari a preparare l’utilizzo di questa funzionalità sonoforniti da Google per le versioni “premium” ed “educational” delle loro so-luzioni web: per la versione base non è possibile usare la 2-legged authen-tication per impersonare un’altro utente, ed è quindi necessario possederele sue credenziali per avere accesso ai suoi dati o anche semplicementecaricare un file.

La classe DocumentsService può essere istruita ad occuparsi au-tonomamente dell’autenticazione con queste modalità, sostituendo il suogeneratore di richieste RequestFactory con un oggetto creato ad hocin tal senso; una volta che GooglePremiumAuthenticator dietro lescene ha compiuto queste operazioni, l’autenticazione avverrà in manieratrasparente.

5.4 Setup dei sistemi di archiviazione

Allo stato attuale delle cose, non è stato ancora rilasciato un prodottofinito (come ad esempio un plug in) che permetta il fluire dei dati di-rettamente da GEC a uno dei sistemi di terza parte proposti secondomodalità certe e definitive, poiché non sono ancora chiari i dettagli sulcome trarre maggior vantaggio dal sistema creato.

Page 104: Tesi Todone

98 5. Sottosistema di archiviazione e plug in

Esistono invece una serie di esempi e scheletri di codice pronti dariempire con pochissime righe di codice, per permettere a qualsiasisviluppatore—anche con scarsa formazione sul progetto—di condizionareil sistema a operare nel modo che egli ritenga più opportuno.

Il setup del sistema di plug in dal lato di GEC_Scan è banale, e con-siste semplicemente nell’assicurarsi che gli assembly contenenti i plug indesiderati risiedano nella cartella plugins, all’interno della cartella prin-cipale del programma, o eventualmente in un’altra cartella specificatanell’apposita sezione del file di configurazione ( 4.4 nella pagina 70).

Per quanto riguarda i servizi esterni, si rimanda alle guide di Goo-gle e Microsoft rispettivamente per la registrazione e l’utilizzo del ser-vizio Google Documents e per l’istallazione e configurazione di base diSharepoint.

Per entrambi i servizi è necessario creare utenti corrispondenti agliutilizzatori finali del sistema: con il solo Sharepoint è necessario dellavoro aggiuntivo per la creazione di un sito e di una lista all’internodello stesso, operazioni facilitate dall’utilizzo di templates. A meno diesigenze particolari, una semplice lista di file è sufficiente per cominciaread utilizzare il servizio in congiunzione col sistema software proposto.

L’indirizzo http esatto del sito creato e il nome o l’identificatoreunivoco della lista in esso contenuta sono necessari per il successivoaccesso al servizio Sharepoint, anche se probabilmente la loro gestio-ne sarà resa automatica e trasparente nell’incarnazione finale del si-stema; analoghe considerazioni per entrambi i servizi di archiviazionevanno fatte per username e password, e—nel caso dell’utilizzo della2-legged-authentication—anche per il cosiddetto “consumer secret”.

Page 105: Tesi Todone

Capitolo 6Conclusioni

Nel corso del tirocinio svolto presso MIDA4 si è affrontato un caso distudio concreto nato dalla reale necessità di tale ditta. Questo caso distudio ha portato in maniera naturale al porsi l’obiettivo principale dellavoro poi svolto come tesi: la produzione di un software che implemen-tasse alcune funzioni di archiviazione documenti. Tale software dovevaintegrarsi nel modo più indolore possibile con più grandi realtà softwaregià esistenti e funzionanti.

È stato creato non un software, ma un intero kit di sviluppo checonsta di tre moduli indipendenti e di una lunga serie di software per iltest e la configurazione di aspetti secondari legati al lavoro principale.

Ciò è stato possibile utilizzando numerose e diverse tecnologie: re-centi, come l’ambiente di sviluppo Microsoft, il framework dotNet, i webserver, e meno recenti—per esigenze particolari o ragioni di compatibilitàcon altre componenti del progetto—come TWAIN o COM. Il risultato èun sistema che fa dell’interoperabilità il suo punto di forza.

Col software prodotto è possibile acquisire ed organizzare i flussi didati forniti dagli utenti del programma di scansione, ed indirizzarli versoserver locali e remoti a fini di validazione, archiviazione, interpretazione.Si può cioè richiedere ad un utente di fornire documenti e dati che, unavolta acquisiti, potranno essere memorizzati, inseriti in un meccanismodi approvazione o analizzati (ad esempio da un software OCR).

99

Page 106: Tesi Todone

100 6. Conclusioni

Ci si è concentrati sull’archiviazione semplice, ignorando cioè le di-sposizioni di legge che riguardano la cosiddetta conservazione ottica so-stitutiva, necessaria qualora si desiderasse conservare informaticamentecopie uniche di documenti con valore legale; nonostante ciò, l’architettu-ra generale del sistema non vieta di aggiungere in un secondo momentole funzionalità di firma ed apposizione di marca temporale—necessarie atale fine—qualora la software house MIDA4 ne sentisse il bisogno.

Possibili sviluppi futuri del lavoro esposto potrebbero quindi toccarei temi della conservazione sostitutiva, della produzione di un sistema chegestisca la dematerializzazione dei documenti o ancora lo sviluppo di ser-vizi web dedicati alla conversione di immagini in documenti strutturati,a fini di indicizzazione ed interpretazione automatica.

Page 107: Tesi Todone

Ringraziamenti

In primis un ringraziamento speciale al prof. Alberto Bartoli che ha sa-puto creare nel suo “Laboratorio Reti” una realtà come poche all’inter-no dell’Università di Trieste, mettendo insieme collaboratori brillanti edaffiatati, ed ottenendo i risultati che giustamente ne conseguono.

Un grazie anche alla MIDA4 che ha reso possibile lo sviluppo di que-sto elaborato, nonché all’ ing. Giorgio Davanzo che più che un correlatoredi forma è stato un collaboratore reale, presente e sempre disponibile edall ing. Eric Medvet, che per onestà (?) ha rifiutato di essere citato comecorrelatore pur avendo subito abbondantemente le mie continue richiested’aiuto.

Un grazie al resto del laboratorio sempre pronto a dare una mano,ad Elisa per il “consulto legale” (e per il computer!) ed a tutti quelli tragenitori, parenti ed amici che mi hanno sopportato in questi lunghi mesi.

Grazie a tutti.

101

Page 108: Tesi Todone
Page 109: Tesi Todone

Bibliografia

[1] The atom publishing protocol - http://tools.ietf.org/html/rfc5023.

[2] The atom syndication format - http://tools.ietf.org/html/rfc4287.

[3] Accademia della crusca. Risposte ai quesiti - http://www.accademiadellacrusca.it/faq/faq_risp.php?id=4092&ctg_id=44.

[4] Google. Google data apis overview - http://code.google.com/intl/it-IT/apis/gdata/overview.html.

[5] TWAIN Working Group. Twain specification version 1.9a - http://www.twain.org/docs/TWAIN19.pdf.

[6] Rudyard Kipling. The ballad of east and west.

[7] MSDN. Batch updating list items in windows sharepoint ser-vices 3.0 - http://msdn.microsoft.com/en-us/library/cc404818.aspx.

[8] MSDN. Createfile function - http://msdn.microsoft.com/en-us/library/aa363858(VS.85).aspx.

103

Page 110: Tesi Todone

104 BIBLIOGRAFIA

[9] MSDN. Filesystemwatcher - http://msdn.microsoft.com/it-it/library/system.io.filesystemwatcher(VS.80).aspx. Riferimento a .NET Framework.

[10] MSDN. Hooks - http://msdn.microsoft.com/en-us/library/ms632589(VS.85).aspx.

[11] MSDN. sealed - http://msdn.microsoft.com/en-us/library/88c54tsw(VS.71).aspx. C# Programmer’s Referen-ce.

[12] MSDN. Xml serialization in the .net framework - http://msdn.microsoft.com/en-us/library/ms950721.aspx. XMLand the .NET Framework.

[13] Wikipedia. Hooking - http://en.wikipedia.org/wiki/Hooking.