Faina Biomedica



Software libero

Software Opne Source

Medicina e Open Source

Errori tipici Linux

Variabili d'ambiente Linux

Wireless e Linux

GNUmed

MySQL Trigger

DICOM-DCMTK

XML LINUX

XMLBeans

WEB SERVICE

Sistemi ad Eventi

Codice Dispatcher sistema ad eventi

Codice dell code

Contatto


Cos'è il Software Libero?

Il “Software Libero” è una questione di libertà, non di prezzo. Per capire il concetto, bisognerebbe pensare alla “libertà di parola” e non alla “birra gratis”. (NdT: il termine “free” in inglese significa sia gratuito che libero).

L'espressione “Software Libero” si riferisce alla libertà dell'utente di eseguire, copiare, distribuire, studiare, cambiare e migliorare il software. Più precisamente, esso si riferisce a quattro tipi di libertà per gli utenti del software:
Libertà di eseguire il programma, per qualsiasi scopo (libertà 0).
Libertà di studiare come funziona il programma e adattarlo alle proprie necessità (libertà 1). L'accesso al codice sorgente ne è un prerequisito.
Libertà di ridistribuire copie in modo da aiutare il prossimo (libertà 2).
Libertà di migliorare il programma e distribuirne pubblicamente i miglioramenti, in modo tale che tutta la comunità ne tragga beneficio (libertà 3). L'accesso al codice sorgente ne è un prerequisito. ...


open source


Open source is a development method for software that harnesses the power of distributed peer review and transparency of process. The promise of open source is better quality, higher reliability, more flexibility, lower cost, and an end to predatory vendor lock-in.

The Open Source Initiative (OSI) is a non-profit corporation formed to educate about and advocate for the benefits of open source and to build bridges among different constituencies in the open-source community.

One of our most important activities is as a standards body, maintaining the Open Source Definition for the good of the community. The Open Source Initiative Approved License trademark and program creates a nexus of trust around which developers, users, corporations and governments can organize open-source cooperation. ....

SU

Qui vi segnalo alcuni software open source

Sapevo dell'esistenza di un software equivalente a Matlab ovvero di Octave ma non l'avevo mai preso in considerazione. Questi giorni l'ho guardato con più attenzione e per quello che serve a noi a elaborazione dei segnali biomedici è sufficiente.

Potete scaricarlo sia per windows che per linux al sito http://sourceforge.net/project/showfiles.php?group_id=2888.

Per maggiori informazioni sul software guardare il sito http://www.gnu.org/software/octave/.

Per i tool che si possono aggiungere guardare il sito http://octave.sourceforge.net/packages.html.



SU

Medicina e Open Source

Ho sviluppato la tesi del terzo anno su care2x un His open source scritto in php. Questo software è completo ma è molto difficile da usare.

Ho guardato anche lo standard DICOM durante lo sviluppo di una relazione per un esame. Questo è uno standard usato per i risultati della diagnostica per immagini. Non definisce un formato per le immagini me piuttosto un modo standard per trattarle.

Ho sviluppato un sistema ad eventi per collegare tra loro i vari sistemi presenti in una struttura sanitaria per la tesi del V anno.

SU

Errori tipici incontrati nel lavorare con Linux

Non riuscivo a capire perché non mi girava il file.sh, mi dava questo errore, lo aprivo con un normale editor di testo e non vedevo niente di anomalo. Allora come ultima prova lo ho aperto con vi da linea di comada e magicamente sono spuntati fuori i sipoli “^M” alla fine di ogni riga.

SU

Variabili d'ambiente Linux

SU

Wireless e Linux

Se non esistono i driver per linux bisogna usare quelli per windows. Dopo averli scaricati da internet li decomprimiamo e individuiamo il file.inf all'interno della cartella decompressa.

Ora installiamo ndisreapper e poi digitiamo i seguenti comandi:

cd /the_dir_you_put_the_wlan_drivers_into/

sudo ndiswrapper -i bcmwl5.inf (fill out your own drivers for bcmwl5.inf)

sudo ndiswrapper -l (shows if the driver is installed)

sudo modprobe ndiswrapper

sudo dmesg (shows that the card is installed (hopefully))

sudo iwlist wlan0 scan (shows all APs surrounding you)

sudo ndiswrapper -m

sudo iwconfig wlan0 essid name_of_AP (the name you found by using iwlist wlan0 scan)

iwconfig wlan0 enc <key> (fill out your WEP key (if you have one))

sudo dhclient wlan0 (gets a dynamic IP adress)

sudo ping -c 3 www.ubuntu-linux.nl (tests the connection)

Per maggiori informazioni guarda il seguente forum: http://ubuntuforums.org/showthread.php?t=31926.

SU

GNUmed

GNUMed http://www.vondoczudoc.de/viewtopic.php?t=718
Pacchetti Synaptic: gnumed-common, gnumed-client
Per quanto riguarda il server bisogna installare: postgresql-8.1 postgresql-client-8.1 postgresql-doc-8.1 pgadmin3 pgagent python-pgsql python-psycopg2 python-glade-1.2 python-glade2 glade gimp.
Ora da linea di comando digitiamo
sudo su postgres -c psql postgres
e poi
ALTER USER postgres WITH PASSWORD 'password' ;
questo ci servirà per settare la password di postgresql
Ora bisogna lanciare il file net_install-gnumed_server.sh
A questo punto installiamo con Synaptic pgadmin3.
Lanciamo PGAdmin III dal menu di Kde poi vai su File e quindi add a New Server
ora compila i campi 'address'(localhost), 'description', and 'password'.
Ora modifichiamo il file di configurazione di postgresql come indicato nel sito http://wiki.gnumed.de/bin/view/Gnumed/Configurepostgresql
Apriamo il file /etc/postgresql/8.3/main/pg_hba.conf e poi
Add the three lines below, placing them
* toward the end of the "local" section, meaning after the line " local all postgres ident sameuser "
* but just before the line " local all all ident sameuser "
# allow anyone knowing the proper password to
# log into our GNUmed databases
local samegroup +gm-logins md5
Ora modificare il file gnumed.con della cartella .gnumed all'interno della tua home:
# GNUmed system-wide configuration file
# -------------------------------------------------------------
# see also: http://wiki.gnumed.de/bin/view/Gnumed/ConfigFiles
# -------------------------------------------------------------
# []

[profile public GNUmed database]
host = salaam.homeunix.com port = 5432
database = gnumed_v8


# GNUmed system-wide configuration file
# -------------------------------------------------------------
#
# see also: http://wiki.gnumed.de/bin/view/Gnumed/ConfigFiles
#
# -------------------------------------------------------------


[workplace]

# This name is used to describe the workstation at the
# business logic level, eg. "ultrasound room machine 1",
#
# Many configuration options stored in the backend
# are tied to this name.
name = GNUmed Default



[backend]

# during login the user can chose from several
# profiles defining which GNUmed database server
# to connect to,
#
# the profiles themselves are defined further below
#
profiles = $profiles$
public GNUmed database
local GNUmed database
$profiles$



[profile public GNUmed database]
host = salaam.homeunix.com
port = 5432
database = gnumed_v8
#encoding = UTF8



[profile local GNUmed database]
host = localhost
port = 5432
database = gnumed_v8
#encoding = UTF8

SU



MySQL Trigger
Nel nostro sistema ad eventi è necessario che i vari sistemi locali inviino a Mirth gli eventi in automatico appena sono generati. Spesso però questi sistemi non hanno gli strumenti per farlo. A questo proposito ci viene in aiuto MySQL (certo questo metodo può essere usato solo qual'ora il software sia sviluppato sul database MySQL).
Dalla versione 5.0 di MySQL è stato inserito in questo DBMS un tool per creare notifiche all'accadimento di eventi.
Per generare queste notifiche è necessario il seguente scrip:
CREATE TRIGGER trigger name { BEFORE | AFTER }
{ INSERT | UPDATE | DELETE }
ON table name
FOR EACH ROW
triggered SQL statement
trigger name: nome arbitrario del trigger;
BEFORE: indica se lo statement SQL deve essere eseguito prima l'accadimento dell'evento;
AFTER: indica se lo statement SQL deve essere eseguito dopo l'accadimento dell'evento;
INSERT: è l'evneto di insersione di un record;
UPDATE: è l'evento di aggiornamento di un record;
DELETE: è l'evento di cancellazione di un record;
ON table name: indica il nome della tabela dove avviene l'evento;
triggered SQL statement: qui deve essere inserito lo statement SQL che va eseguito all'accadimento dell'evento.
I trigger che servono a noi sono quindi:
create trigger nome_trigger
before insert on nome_tabella
for each row
set new.nome_colonna_stato = valore1;
Questo va fatto per ogni tabella di cui vogliamo notificare l'inserimento di un record. Se vogliamo notificare l'evento di modifica o cancellazione di un record basta sostituire insert con delete o update.
Inoltre è essenziale che ogni tabella abbia un campo per lo stato.
Appena Mirth ha prelevato i record con il valore della colonna stato uguale a valore1 bisogna immediatamente cambiare valore1 con un nuovo valore il che renderà possibile distinguere i record già prelevati da quelli non ancora prelevati. Per fare quest'ultima cosa è essenziale che da Mirth eseguiamo lo statement SQL:
update nome-tabella set nome_colonna_stato = valore2;

SU

DICOM-DCMTK

DCMTK è una raccolta di librerie e applicazioni che implementano gran parte dello standard DICOM. Questa raccolta include software per esaminare, costruire e convertire i file di immagini DICOM, inviare e ricevere immagini attraverso la rete, salvare file e software che fungono da worklist server. DCMTK è scritto in un misto di C e C++, è open source.

Questa raccolta è usata da ospedali e compagnie nel mondo per una vasta gamma di applicazioni che vanno dal test di software, alla ricerca, prodotti commerciali e prototipi.

Il software DCMTK può essere compilato sotto windows e sotto una vasta gamma di sistemi Unix incluso Linux, Solaris, QNX, IRIX, Free/Net/OpenBSD e MacOSX.

DCMTK include i programmi DICOM SCP (Service Class Provider = server) e i SCU (Service Class User = Client).

Ecco i software contenuti nella raccolta:



Implementiamo il nostro PACS

Salvataggio

storescp: Resta in attesa di ricevere file DICOM e quando arrivano li salva in una cartella (car1)

storescu: Invia file DICOM a storescp

Es.

storescp -od car1/ 8788

storescu -d localhost 8788 IM-0001-1624.dcm



Converte da DICOM a XML

* dcm2xml

dcm2xml IM-0001-1624.dcm IM-trasformato.xml

Nel file xml abbiamo stringhe del tipo:

<element tag="0008,1010" vr="SH" vm="1" len="8" name="StationName">CT54023</element>

Per estrarre una stringa da un file e metterla in una variabile d'ambiente si devi digitare:

val=$(head -1 nomefile)

Per trovare i file che contengono un certo valore digitiamo il seguente comando:

grep -l "%stringa%" %path ricerca% --> mostra il nome di tutti i file che contengono quella stringa.

Nel caso in cui abbiamo estretto la stringa da un file come visto sopra facciamo:

grep -l $val *.xml

Analisi del nostro sistema PACS

Una volta che un file arriva a storescp viene messo nella cartella scelta (car1).

Con un programma che si attiva ad intervalli regolari andiamo a convertire in formato xml tutti i file presenti nella cartella car1 e il risultato della conversione lo mettiamo in car2, il nome del file convertito è lo stesso di quello originale. Per evitare che al prossimo caricamento del programa si vadano a convertire gli stessi file spostiamo i file originali da car1 a car3.

Con lo script sotto trovo i nuovi file inviati per lo stoccaggio e una volta individuati li converto in xml in modo che poi li posso andare a ricercare:

script_converti.sh

#!/bin/sh

find car1 -type f | wc -l > num_file

val=$(head -1 num_file)

ls -l car1 --sort=time > elenco_file_ordinato_per_data

cat elenco_file_ordinato_per_data | awk '{print $8}'> nomi_file_ordinati_per_data

sed 1d nomi_file_ordinati_per_data > nomi_file_ordinati_per_data_0

count=0

n=$val

echo $n

until [ $n -eq 0 ]

do

n=$(($val-$count))

nome_file=$(head -1 nomi_file_ordinati_per_data_$count)

echo $nome_file > nome_file_$count

sed 1d nomi_file_ordinati_per_data_$count > nomi_file_ordinati_per_data_$(($count+1))

dcm2xml car1/$nome_file car2/$nome_file

cp car1/$nome_file car3/$nome_file

rm car1/$nome_file

count=$(($count+1))

done

Questo script va eseguito solo se val >0.



Script per cercare una stringa in un file xml:

script_cerca.sh

#!/bin/sh

val=$(head -1 nomefile_contenente_stringa_da_cercare)

grep -l $val *.xml > file_che_contiene_il_nome_del_file_dicom_trovato

[1]

RLE

In informatica, l'algoritmo Run-length encoding (RLE) è storicamente il primo algoritmo di compressione per le immagini inventato, utilizzato nei fax ben prima che le elaborazioni grafiche al computer fossero un'attività comune. L'RLE è lossless (senza perdita di informazioni), ovvero permette di comprimere e decomprimere senza alcuna perdita di informazione.

Solitamente si applica alle immagini e si fonda sull'assunto che l'immagine abbia pochi colori, ma può essere utilizzato su qualunque file dove si trovino lunghe sequenze dove lo stesso byte viene ripetuto. La compressione RLE viene spesso impiegata anche nei protocolli di rete (ad esempio, IBM SNA) o nei formati di dati di applicazioni in cui il tempo di elaborazione è critico (ad esempio, alcuni filmati AVI), perché è il formato che permette la maggior velocità di decompressione.

L'algoritmo di RLE cerca nei dati da comprimere una serie di elementi uguali (in un'immagine bitmap, essa corrisponde ad una campitura piatta), e la sostituisce con un solo elemento, quindi un carattere speciale e infine il numero di volte che esso va ripetuto. Per esempio supponiamo di avere un'immagine dove la prima riga è formata da cento pixel neri, il RLE memorizzerà il primo pixel nero poi metterà il carattere speciale e in seguito memorizzerà il numero 100. Così invece di occupare cento locazioni la prima riga ne occuperà solo 3. Il carattere speciale è definito diversamente da ogni implementazione dell'algoritmo, e serve a distinguere un elemento normale da uno compresso.

Questo algoritmo funziona bene in presenza di immagini con pochi colori molto uniformi, ovvero in serie di dati che abbiano molte ripetizioni al loro interno.

(http://it.wikipedia.org/wiki/Run-length_encoding)

[2]

DICOM Part 10 Data Loading

Quando si caricano dati DICOM, ci si riferisce alla directory dell'ultima operazione DICOM. Se esiste un file DICOMDIR nella directory, solo gli studi registrati nel DICOMDIR sono presentati per essere caricati. Se non esiste il file DICOMDIR, tutti i file nella directory sono scandagliati e tutti gli studi DICOM validi sono listati.

(http://www.pmod.com/technologies/doc/pbas/689.htm)

[3]

DICOMDIR

Il formato file DICOMDIR è stato difinito per accedere per accedere ai DICOM part 10 files. Per esempio, i CD DICOM compliant contengono in DICOMDIR al livello root tutte le descrizioni e le informazioni di accesso per tutti gli studi nel CD.

(http://www.pmod.com/technologies/doc/pbas/1990.htm)

[4]

Un Presentation State è un DICOM SOP indipendente che contiene informazioni su come una particolare immagine deve essere mostrata. Il Presentation State può contenere informazioni su: tipo, posizione, valori sulla finestre, valori di zoom, valori sullo scrolling (panning), rotazione o altri elementi per la vusualizzazione che sono definiti nello standard DICOM. Bisogna dire che il Presentation States non contiene informaizoni su i Pixel Data. Il vantaggio dell'uso del presentation states è che è sempre possibile tornare indietro all'immagine origianel in quanto i pixel non sono modificati ma solo come questa è mostrata. Il Presentation states può essere inviato al PACS (se il PACS sipporta le classi Presentations state SOP) e ritrovata quando richiesta.

(http://www.medicalconnections.co.uk/wiki/Presentation_states)

[5]

DICOM SR

Formato per i referti.

SU



XML Linux

Command line XML toolkit

XMLStarlet is a set of command line utilities (tools) which can be used to transform, query, validate, and edit XML documents and files using simple set of shell commands in similar way it is done for plain text files using UNIX grep, sed, awk, diff, patch, join, etc commands.

This set of command line utilities can be used by those who deal with many XML documents on UNIX shell command prompt as well as for automated XML processing with shell scripts.

The toolkit's feature set includes options to:

SU



XMLBeans

XMLBeans è una libreria scritta dalla Apache che permette di manipolare il contenuto di un file XML fornendo una visione a oggetti dei dati e implementando tutte le funzionalità necessarie allo sviluppatore per gestire in modo automatico le operazioni di lettura, scrittura e validazione di un file XML. La versione che utilizzeremo nel nostro esempio è la 2.3.0.

Mediante XMLBeans è possibile generare delle classi java che permettono di leggere, scrivere o validare un file xml. Per generare le classi occorre preparare un file xsd nel quale sono definite tutte le regole a cui i file XML devono essere conformi.

Per utilizzare XmlBeans bisogna settare le seguenti variabili di ambiente:

* XMLBEANS_HOME contenente il path della root di XMLBeans;

* JAVA_HOME contenente il path della root del JDK;

* Aggiungere al CLASSPATH la libreria %XMLBEANS_HOME%\lib\xbean.jar

è necessario inoltre aggiungere alla variabile di ambiente PATH la cartella bin del JDK e la directory bin di XMLBeans.

Come esempio creeremo le classi java che serviranno per leggere e scrivere file XML del tipo:

Listato 1. Esempio di un XML

<iscritti>

<iscritto matricola="..." nome="..." cognome="...">

<esame voto="..">..</esame>

<esame voto="..">..</esame>

<esame voto="..">..</esame>

</iscritto>

<iscritto matricola="..." nome="..." cognome="...">

<esame voto="..">..</esame>

</iscritto>

<iscritto matricola="..." nome="..." cognome="...">

</iscritto>

...

</iscritti>

Il tag principale è "iscritti", che può contenere da zero a n tag "iscritto". Ciascun iscritto ha tre attributi (matricola, nome e cognome) e può contenere zero o n tag esame. Ciascun esame ha un attributo (voto) e, il suo valore, rappresenta l'esame sostenuto dallo studente.

Prima di tutto bisogna scrivere il file xsd nel quale viene definita tale struttura. Scrivere a mano un file xsd non è semplicissimo, in aiuto ci viene XMLSpy che ci permette di scriverlo sfruttando le classiche tecniche del drag & drop.

(http://java.html.it/articoli/leggi/2367/xmlbeans/)

Listato 2. Esempio di un file XSD

<?xml version="1.0" encoding="UTF-8"?>

<!-- edited with XMLSpy v2007 rel. 3 sp1 by Luca -->

<xs:schema xmlns:xs=http://www.w3.org/2001/XMLSchema xmlns:sf=http://www.sportfantasy.org

targetNamespace="http://www.sportfantasy.org" elementFormDefault="qualified" attributeFormDefault="unqualified">

<xs:complexType name="iscritto">

<xs:sequence minOccurs="0" maxOccurs="unbounded">

<xs:element name="esame">

<xs:complexType>

<xs:simpleContent>

<xs:extension base="xs:string">

<xs:attribute name="voto">

<xs:simpleType>

<xs:restriction base="xs:int">

<xs:maxInclusive value="30"/>

<xs:minInclusive value="18"/>

</xs:restriction>

</xs:simpleType>

</xs:attribute>

</xs:extension>

</xs:simpleContent>

</xs:complexType>

</xs:element>

</xs:sequence>

<xs:attribute name="matricola" type="xs:string" use="required"/>

<xs:attribute name="nome" type="xs:string" use="required"/>

<xs:attribute name="cognome" type="xs:string" use="required"/>

</xs:complexType>

<xs:element name="iscritti">

<xs:annotation>

<xs:documentation>Comment describing your root element</xs:documentation>

</xs:annotation>

<xs:complexType>

<xs:sequence maxOccurs="unbounded">

<xs:element name="iscritto" type="sf:iscritto"/>

</xs:sequence>

</xs:complexType>

</xs:element>

</xs:schema>

Per generare le classi java che permettono di gestire i file XML conformi alla seguente struttura apriamo una shell, portiamoci nella directory nella quale è contenuto il file xsd (iscritti.xsd) appena creato e lanciamo il seguente comando:

scomp iscritti.xsd –out iscritti.jar

Con questo comando viene creata la libreria (iscritti.jar) che contiene le classi java che ci permettono di scrivere e leggere i file XML compatibili con l'xsd. Le classi hanno come package uguale al namespace URI dell'xsd. Nel nostro caso org.sportfantasy.

La classe principale è IscrittiDocument che incapsula l'intero documento XML. Per ciascun tipo complesso definito nell'xsd è stata generata un'interfaccia e una classe che la implementa. Tutte le classi hanno a disposizione i metodi getter e setter rispettivamente per leggere e scrivere le proprietà dell'oggetto. Ad esempio la classe Iscritto avrà come metodo getNome() e setNome(). Naturalmente l'attrbuto nome della classe Iscritto è di tipo stringa così come definito nell'xsd. Poichl tag iscritti può contenere n tag iscritto, la classe Iscritti avrà a disposizione un metodo che permette di aggiungere un Iscritto (addNewIscritto()). Allo stesso modo la classe Iscritto avrà a disposizione un metodo che permette di aggiungere un Esame (addNewEsame()).

Notiamo che ogni interfaccia che rappresenta un elemento dell'XML schema, contiene un'inner class "Factory", creata secondo il pattern abstract Factory, che permette di creare un oggetto java che incapsula l'elemento. Ad esempio il comando IscrittiDocument.Factory.newInstance() ci permette di ottenere un'istanza del documento.

Vediamo come utilizzare la libreria per scrivere un file xml conforme alla struttura definita.

Listato 3. Utilizzo della libreria per scrivere un file xml

import java.io.File;

import java.io.IOException;

import org.apache.xmlbeans.XmlOptions;

import org.sportfantasy.IscrittiDocument;

import org.sportfantasy.Iscritto;

import org.sportfantasy.IscrittiDocument.Iscritti;

import org.sportfantasy.Iscritto.Esame;

public class Scrittura

{

public static void main(String[] args) throws IOException

{

//doc è un'istanza del documento xml

IscrittiDocument doc = IscrittiDocument.Factory.newInstance();

//aggiungiamo un tag iscritti al documento

Iscritti studenti = doc.addNewIscritti();

//aggiungiamo uno studente e settiamo i sui attributi

Iscritto studente1 = studenti.addNewIscritto();

studente1.setMatricola("544-843");

studente1.setNome("Pippo");

studente1.setCognome("Baudo");

//aggiungiamo un esame allo studente e settiamo gli attributi

Esame esame1 = studente1.addNewEsame();

esame1.setVoto(18);

esame1.setStringValue("Programmazione");

//aggiungiamo un altro esame allo studente e settiamo gli attributi

Esame esame2 = studente1.addNewEsame();

esame2.setVoto(30);

esame2.setStringValue("Tecnologie WEB");

//aggiungiamo un altro studente e settiamo i sui attributi

Iscritto studente2 = studenti.addNewIscritto();

studente2.setMatricola("503-1092");

studente2.setNome("Mike");

studente2.setCognome("Buongiorno");

//aggiungiamo un esame allo studente e settiamo gli attributi

Esame esame3 = studente2.addNewEsame();

esame3.setVoto(30);

esame3.setStringValue("Analisi 2");

//settiamo le opzioni utilizzate per la stampa o la scrittura

XmlOptions opts = new XmlOptions();

//questa opzione permette di indentare il codice xml

opts.setSavePrettyPrint();

System.out.println(doc.xmlText(opts));

//salviamo il file sul disco

doc.save(new File ("C:/test.xml"), opts);

}

}

Vediamo, infine, come utilizzare la libreria per la lettura di un file xml conforme alla struttura definita.

Listato 4. Utilizzo della libreria per leggere un file xml

import java.io.File;

import org.sportfantasy.IscrittiDocument;

import org.sportfantasy.Iscritto;

import org.sportfantasy.IscrittiDocument.Iscritti;

import org.sportfantasy.Iscritto.Esame;

public class Lettura

{

public static void main(String[] args) throws Exception

{

//caricamento del file xml

IscrittiDocument doc = IscrittiDocument.Factory.parse(new File ("C:/test.xml"));

//root è un'istanza del documento xml

Iscritti root = doc.getIscritti();

//studenti è un array di oggetti Iscritto

Iscritto[] studenti = root.getIscrittoArray();

System.out.println("STUDENTI ISCRITTI: " + studenti.length);

for (int i=0; i<studenti.length; i++)

{

//lettura dell'iesimo iscritto

Iscritto studente = root.getIscrittoArray(i);

System.out.println(studente.getNome() + " " + studente.getCognome() + " " + studente.getMatricola());

for (int j=0; j<studente.getEsameArray().length; j++)

{

//lettura del j'esimo esame

Esame esame = studente.getEsameArray(j);

System.out.println(esame.getStringValue()+ " " + esame.getVoto());

}

System.out.println();

}

}

}

www.html.it

SU



Web Service

Architettura di J2EE L' architettura proposta dalla piattaforma J2EE divide le applicazioni enterprise in tre strati applicativi fondamentali: componenti, contenitori e connettori. Il modello di programmazione prevede lo sviluppo di soluzioni utilizzando componenti a supporto delle quali fornisce quattro tecnologie fondamentali:


Enterprise Java Beans;
Servelet ;
Java Server Pages ;
Applet.


La prima delle quattro che per semplicità denoteremo con EJB fornisce supporto per la creazione di componenti server-side che possono essere generate indipendentemente da uno specifico database, da uno specifico transaction server o dalla piattaforma su cui gireranno. La seconda, servlet, consente la costruzione di servizi web altamente performanti ed in grado di funzionare sulla maggior parte dei web server ad oggi sul mercato. La terza, JavaServer Pages o JSP, permette di costruire pagine web dai contenuti dinamici utilizzando tutta la potenza del linguaggio java. Le applet, anche se sono componenti client-side rappresentano comunque tecnologie appartenenti allo strato delle componenti.
Il secondo strato è rappresentato dai contenitori ovvero supporti tecnologici alle tecnologie appartenenti al primo strato logico della architettura. La possibilità di costruire contenitori rappresenta la caratteristica fondamentale del sistema in quanto fornisce ambienti scalari con alte performance.
Infine i connettori consentono alle soluzioni basate sulla tecnologia J2EE di preservare e proteggere investimenti in tecnologie già esistenti fornendo uno strato di connessione verso applicazioni-server o middleware di varia natura: dai database relazionali con JDBC fino ai server LDAP con JNDI.


J2EE Application Model
Date le caratteristiche della piattaforma, l' aspetto più interessante è legato a quello che le applicazioni non devono fare; la complessità intrinseca delle applicazioni enterprise quali gestione delle transazioni, ciclo di vita delle componenti, pooling delle risorse viene inglobata all' interno della piattaforma che provvede autonomamente alle componenti ed al loro supporto.
Programmatori e analisti sono quindi liberi di concentrarsi su aspetti specifici della applicazione come presentazione o logiche di business non dovendosi occupare di aspetti la cui complessità non è irrilevante e, in ambito progettuale ha un impatto notevolissimo su costi e tempi di sviluppo.
A supporto di questo, l' Application Model descrive la stratificazione orizzontale tipica di una applicazione J2EE. Tale stratificazione identifica quattro settori principali : Client Tier, Web Tier, Business-Tier, EIS-Tier.


Client Tier
Appartengono allo strato client le applicazioni che forniscono all' utente una interfaccia semplificata verso il mondo enterprise e rappresentano quindi la percezione che l' utente ha della applicazione J2EE. Tali applicazioni si suddividono in due classi di appartenenza : le applicazioni web-based e le applicazioni non-web-based.
Le prime sono quelle applicazioni che utilizzano il browser come strato di supporto alla interfaccia verso l' utente ed i cui contenuti vengono generati dinamicamente da Servlet o Java Server Pages o staticamente in HTML. Le seconde (non-web-based) sono invece tutte quelle basate su applicazioni stand-alone che sfruttano lo strato di rete disponibile sul client per interfacciarsi direttamente con la applicazione J2EE senza passare per il Web-Tier.


Web Tier
Le componenti web-tier di J2EE sono rappresentate da pagine JSP, server-side applet e Servlet. Le pagine HTML che invocano Servlet o JSP secondo lo standard J2EE non sono considerate web-components, ed il motivo è il seguente : come illustrato nei paragrafi precedenti si considerano componenti, oggetti caricabili e gestibili all'interno di un contenitore in grado di sfruttarne i servizi messi a disposizione. Nel nostro caso, Servlet e JSP hanno il loro ambiente runtime all'interno del "Servlet-Container" che provvede al loro ciclo di vita, nonché alla fornitura di servizi quali client-request e client-response ovvero come un client appartenente allo strato client-tier rappresenta la percezione che l'utente ha della applicazione J2EE, il contenitore rappresenta la percezione che una componente al suo interno ha della interazione verso l'esterno.
La piattaforma J2EE prevede quattro tipi di applicazioni web : "basic HTML", "HTML with base JSP and Servlet" " , Servlet and JSP with JavaBeans components", "High Structured Application con componenti modulari", "Servlet ed Enterprise Beans" Di queste, le prime tre sono dette "applicazioni web-centric" quelle appartenenti al quarto tipo sono dette " applicazioni EJB Centric" La scelta di un tipo di applicazione piuttosto che di un altro dipende ovviamente da vari fattori tra cui:
Complessità del problema;
Risorse del Team di sviluppo;
Longevità della applicazione;
Dinamismo dei contenuti da gestire e proporre.


Business Tier
Nell' ambito di una applicazione enterprise, è questo lo strato che fornisce servizi specifici: gestione delle transazioni, controllo della concorrenza, gestione della sicurezza, ed implementa inoltre logiche specifiche circoscritte all' ambito applicativo ed alla manipolazione dei dati. Mediante un approccio di tipo Object Oriented è possibile decomporre tali logiche o logiche di business in un insieme di componenti ed elementi chiamati " business object".
La tecnologia fornita da Sun per implementare i " business object" è quella che in precedenza abbiamo indicato come EJBs (Enterprise Java Beans). Tali componenti si occupano di:
Ricevere dati da un client, processare tali dati (se necessario), inviare i dati allo strato EIS per la loro memorizzazione su base dati; (Viceversa) Acquisire dati da un database appartenente allo strato EIS, processare tali dati (se necessario), inviare tali dati al programma client che ne abbia fatto richiesta.
Esistono due tipi principali di EJBs : entity beans e session beans. Per session bean si intende un oggetto di business che rappresenta una risorsa " privata" rispetto al client che lo ha creato. Un entity bean al contrario rappresenta in modo univoco un dato esistente all'interno dello strato EIS ed ha quindi una sua precisa identità rappresentata da una chiave primaria.
Oltre alle componenti, la architettura EJB definisce altre 3 entità fondamentali: servers, containers e client. Un Enterprise Bean vive all'interno del container che provvede al ciclo vitale della componente e ad una varietà di latri servizi quali gestione della concorrenza e scalabilità. L' EJB Container è a sua volta parte di un EJB server che fornisce tutti i servizi di naming e di directory (tali problematiche verranno affrontate negli articoli successivi).
Quando un client invoca una operazione su un EJB, la chiamata viene intergettata dal container. Questa intercessione del container tra client ed EJB a livello di "chiamata a metodo" consente al container la gestione di quei servizi di cui si è parlato all'inizio del paragrafo oppure della propagazione della chiamata ad altre componenti (Load Balancing) o ad altri container (Scalabilità) su altri server sparsi per la rete su differenti macchine.
Nella implementazione di una architettura enterprise, oltre a decidere che tipo di enterprise beans utilizzare, un programmatore deve effettuare altre scelte strategiche nella definizione del modello a componenti :
Che tipo di oggetto debba rappresentare un Enterprise Bean;
Che ruolo tale oggetto deve avere all' interno di un gruppo di componenti che collaborino tra di loro.
Dal momento che gli enterprise beans sono oggetti che necessitano di abbondanti risorse di sistema e di banda di rete, non sempre è soluzione ottima modellare tutti i business object come EJBs. In generale una soluzione consigliabile è quella di adottare tale modello solo per quelle componenti che necessitino un accesso diretto da parte di un client.


EIS-Tier
Le applicazioni enterprise implicano per definizione l'accesso ad altre applicazioni, dati o servizi sparsi all' interno delle infrastrutture informatiche del fornitore di servizi. Le informazioni gestite ed i dati contenuti all'interno di tali infrastrutture rappresentano la " ricchezza" del fornitore, e come tale vanno trattati con estrema cura garantendone la integrità.
Al modello bidimensionale delle vecchie forme di business legato ai sistemi informativi (figura 11-9) è stato oggi sostituito da un nuovo modello (e-business) che introduce una terza dimensione che rappresenta la necessità da parte del fornitore di garantire accesso ai dati contenuti nella infrastruttura enterprise via web a: partner commerciali, consumatori, impiegati e altri sistemi informativi.
Gli scenari di riferimento sono quindi svariati e comprendono vari modelli di configurazione che le architetture enterprise vanno ad assumere per soddisfare le necessità della new-economy. Un modello classico è quello rappresentato da sistemi di commercio elettronico.
Nei negozi virtuali o E-Store l'utente web interagisce tramite browser con i cataloghi on-line del fornitore, seleziona i prodotti, inserisce i prodotti selezionati nel carrello virtuale, avvia una transazione di pagamento con protocolli sicuri.


Le API di J2EE
Le API di J2EE forniscono supporto al programmatore per lavorare con le più comuni tecnologie utilizzate nell'ambito della programmazione distribuita e dei servizi di interconnessione via rete. I prossimi paragrafi forniranno una breve introduzione alle API componenti lo strato tecnologico fornito con la piattaforma definendo volta per volta la filosofia alla base di ognuna di esse e tralasciando le API relative a Servlet, EJBs e JavaServer Pages già introdotte nei paragrafi precedenti.


JDBC : Java DataBase Connectivity
Rappresentano le API di J2EE per poter lavorare con database relazionali. Esse consentono al programmatore di inviare query ad un database relazionale, di effettuare dolete o update dei dati all'interno di tabelle, di lanciare stored-procedure o di ottenere meta-informazioni relativamente al database o le entità che lo compongono.


RMI : Remote Method Invocation
Remote Method Invocation fornisce il supporto per sviluppare applicazioni java in grado di invocare metodi di oggetti distribuiti su virtual-machine differenti sparse per la rete. Grazie a questa tecnologia è possibile realizzare architetture distribuite in cui un client invoca metodi di oggetti residenti su un server che a sua volta può essere client nei confronti di un altro server.


JNDI
Java Naming and Directory Interface è quell'insieme di API che forniscono l'accesso a servizi generici di Naming o Directory attraverso la rete. Consentono, alla applicazione che ne abbia bisogno, di ottenere oggetti o dati tramite il loro nome o di ricercare oggetti o dati mediante l'uso di attributi a loro associati.


JMS
Java Message Service o Enterprise Messaging rappresentano le API forniscono supporto alle applicazioni enterprise nella gestione asincrona della comunicazione verso servizi di " messaging" o nella creazione di nuovi MOM (Message Oriented Middleware). Nonostante JMS non sia così largamente diffuso come le altre tecnologie, svolge un ruolo importantissimo nell'ambito di sistemi enterprise.
Per meglio comprenderne il motivo è necessario comprendere il significato della parola " messaggio" che in ambito JMS rappresenta tutto l'insieme di messaggi asincroni utilizzati dalle applicazioni enterprise, non dagli utenti umani, contenenti dati relativi a richieste, report o eventi che si verificano all' interno del sistema fornendo informazioni vitali per il coordinamento delle attività tra i processi. Essi contengono informazioni impacchettate secondo specifici formati relativi a particolari "eventi di business" .
Grazie a JMS è possibile scrivere applicazioni di business " message-based" altamente portabili fornendo una alternativa a RMI che risulta necessaria in determinati ambiti applicativi. Nella figura 11-14 è schematizzata una soluzione tipo di applicazioni basate su messaggi. Una applicazione di " Home Banking" deve interfacciarsi con il sistema di messagistica bancaria ed interbancaria da cui trarre tutte le informazioni relative alla gestione economica dell'utente.
Nel modello proposto da J2EE l'accesso alle informazioni contenute all'interno di questo strato è possibile tramite oggetti chiamati " connettori"che rappresentano una architettura standard per integrare applicazioni e componenti enterprise eterogenee con sistemi informativi enterprise anche loro eterogenei.
I connettori sono messi a disposizione della applicazione enterprise grazie al server J2EE che li contiene sotto forma di servizi di varia natura (es. Pool di connessioni) e che tramite questi collabora con i sistemi informativi appartenenti allo strato EIS in modo da rendere ogni meccanismo a livello di sistema completamente trasparente alle applicazioni enterprise. Lo stato attuale dell' arte prevede che la piattaforma J2EE consenta pieno supporto per la connettività verso database relazionali tramite le API JDBC, le prossime versioni della architettura J2EE prevedono invece pieno supporto transazionale verso i più disparati sistemi enterprise oltre che a database relazionali.


Architettura del Web Tier
Introduzione
Chi ha potuto accedere ad internet a partire dagli inizi degli anni 90, quando ancora la diffusione della tecnologia non aveva raggiunto la massa ed i costi erano eccessivi (ricordo che nel 1991 pagai un modem interno usato da 9600 bps la cifra incredibile di 200.000 lire), ha assistito alla incredibile evoluzione che ci ha portato oggi ad una diversa concezione del computer.
A partire dai primi siti internet dai contenuti statici, siamo oggi in grado di poter effettuare qualsiasi operazione tramite Web da remoto. Questa enorme crescita, come una vera rivoluzione, ha voluto le sua vittime. Nel corso degli anni sono nate e poi completamente scomparse un gran numero di tecnologie a supporto di un sistema in continua evoluzione.
Servlet e JavaServer Pages rappresentano oggi lo stato dell'arte delle tecnologie web. Raccogliendo la pesante eredità lasciata dai suoi predecessori, la soluzione proposta da SUN rappresenta quanto di più potente e flessibile possa essere utilizzato per sviluppare applicazioni web.


L'architettura del "Web Tier"
Prima di affrontare il tema dello sviluppo di applicazioni web con Servlet e JavaServer Pages è importante fissare alcuni concetti. Il web-server gioca un ruolo fondamentale all'interno di questo strato. In ascolto su un server, riceve richieste da parte del browser (client), le processa, quindi restituisce al client una entità o un eventuale codice di errore come prodotto della richiesta.
Le entità prodotte da un web-server possono essere entità statiche o entità dinamiche. Una entità statica è ad esempio un file html residente sul file-system del server. Rispetto alle entità statiche, unico compito del web server è quello di recuperare la risorsa dal file-system ed inviarla al browser che si occuperà della visualizzazione dei contenuti.
Quello che più ci interessa sono invece le entità dinamiche, ossia entità prodotte dalla esecuzione di applicazioni eseguite dal web-server su richiesta del client.
Il modello proposto nella immagine 1 ora si complica in quanto viene introdotto un nuovo grado di complessità (Figura 2-12) nella architettura del sistema che, oltre a fornire accesso a risorse statiche dovrà fornire un modo per accedere a contenuti e dati memorizzati su una Base Dati, dati con i quali un utente internet potrà interagire da remoto.


Inviare dati
Mediante form HTML è possibile inviare dati ad un web-server. Tipicamente l'utente riempie alcuni campi il cui contenuto, una volta premuto il pulsante " submit" viene inviato al server con il messaggio di richiesta. La modalità con cui questi dati vengono inviati dipende dal metodo specificato nella richiesta. Utilizzando il metodo GET, i dati vengono appesi alla request-URI nella forma di coppie chiave=valore separati tra di loro dal carattere "?" . La stringa seguente è un esempio di campo request-URI per una richiesta di tipo GET.
http://www.java-net.tv/servelt/Hello?nome=Massimo&cognome=Rossi
"http://www.java-net.tv" rappresenta l'indirizzo del web-server a cui inviare la richiesta. I campi "/servlet/Hello" rappresenta la locazione della applicazione web da eseguire. Il carattere "?" separa l'indirizzo dai dati e il carattere "&" separa ogni coppia chiave=valore.
Questo metodo utilizzato per default dai browser a meno di specifiche differenti, viene utilizzato nei casi in cui si richieda al server il recupero di informazioni mediante query su un database.
Il metodo POST pur producendo gli stessi effetti del precedente, utilizza una modalità di trasmissione dei dati differente impacchettando i contenuti dei campi di un form all'interno di un message-header. Rispetto al precedente, il metodo POST consente di inviare una quantità maggiore di dati ed è quindi utilizzato quando è necessario inviare al server nuovi dati affinché possano essere memorizzati all'interno della Base Dati.
Sviluppare applicazioni web
A meno di qualche eccezione una applicazione web è paragonabile ad una qualsiasi applicazione con la differenza che deve essere accessibile al web-server che fornirà l'ambiente di runtime per l'esecuzione. Affinché ciò sia possibile è necessario che esista un modo affinché il web-server possa trasmettergli i dati inviati dal client, che esista un modo univoco per l'accesso alle funzioni fornite dalla applicazione (entry-point), che l'applicazione sia in grado di restituire al web-server i dati prodotti in formato HTML da inviare al client nel messaggio di risposta.
Esistono molte tecnologie per scrivere applicazioni web che vanno dalla più comune "CGI" a soluzioni proprietarie come ISAPI di Microsoft o NSAPI della Netscape.


Common Gateway Interface
CGI è sicuramente la più comune e datata tra le tecnologie server-side per lo sviluppo di applicazioni web. Scopo principale di un CGI è quello di fornire funzioni di "gateway" tra il web-server e la base dati del sistema.
I CGI possono essere scritti praticamente con tutti i linguaggi di programmazione.
Questa caratteristica classifica i CGI in due categorie: CGI sviluppati mediante linguaggi script e CGI sviluppati con linguaggi compilati. I primi, per i quali viene generalmente utilizzato il linguaggio PERL, sono semplici da implementare, ma hanno lo svantaggio di essere molto lenti e per essere eseguiti richiedono l' intervento di un traduttore che trasformi le chiamate al linguaggio script in chiamate di sistema. I secondi a differenza Dei primi sono molto veloci, ma risultano difficili da programmare (generalmente sono scritti mediante linguaggio C).
Il più grande svantaggio nell' uso dei CGI sta nella scarsa scalabilità della tecnologia infatti, ogni volta che il web-server riceve una richiesta deve creare una nuova istanza del CGI. Il dover stanziare un processo per ogni richiesta ha come conseguenza enormi carichi in fatto di risorse macchina e tempi di esecuzione. A meno di non utilizzare strumenti di altro tipo è inoltre impossibile riuscire ad ottimizzare gli accessi al database. Ogni istanza del CGI sarà difatti costretta ad aprire e chiudere una propria connessione verso il DBMS. Questi problemi sono stati affrontati ed in parte risolti dai Fast-CGI grazie ai quali è possibile condividere una stessa istanza tra più richieste http.


ISAPI ed NSAPI
Per far fronte ai limiti tecnologici imposti dai CGI, Microsoft e Netscape hanno sviluppato API proprietarie mediante le quali creare librerie ed applicazioni che possono essere caricate dal web-server al suo avvio ed utilizzate come proprie estensioni.
L'insuccesso di queste tecnologie è stato però segnato proprio dalla loro natura di tecnologie proprietarie e quindi non portabili tra le varie piattaforme sul mercato.
Essendo utilizzate come moduli del web-server era inoltre caso frequente che un loro accesso errato alla memoria causasse il "crash" dell'intero web-server provocando enormi danni al sistema che doveva ogni volta essere riavviato.


ASP – Active Server Pages
Active Server Pages è stata l'ultima tecnologia web rilasciata da Microsoft. Una applicazione ASP è tipicamente un misto tra HTML e linguaggi script come VBScript o JavaScript mediante i quali si può accedere ad oggetti del server. Una pagina ASP, a differenza di ISAPI, non viene eseguita come estensione del web-server, ma viene compilata alla prima chiamata, ed il codice compilato può quindi essere utilizzato ad ogni richiesta HTTP.
Nonostante sia oggi largamente diffusa, ASP come ISAPI rimane una tecnologia proprietaria e quindi in grado di funzionare solamente su piattaforma Microsoft, ma il reale svantaggio di ASP è però legato alla sua natura di mix tra linguaggi script ed HTML. Questa sua caratteristica ha come effetto secondario quello di riunire in un unico " contenitore" sia le logiche applicative che le logiche di presentazione rendendo estremamente complicate le normali operazioni di manutenzione delle pagine.


Java Servlet e JavaServer Pages
Sun cerca di risolvere i problemi legati alle varie tecnologie illustrate, mettendo a disposizione del programmatore due tecnologie che raccogliendo l'eredità dei predecessori, ne abbattono i limiti mantenendo e migliorando gli aspetti positivi di ognuna. In aggiunta Servlet e JavaServer Pages ereditano tutte quelle caratteristiche che rendono le applicazioni Java potenti, flessibili e semplici da mantenere: portabilità del codice, paradigma object oriented.
Rispetto ai CGI, Servlet forniscono un ambiente ideale per quelle applicazioni per cui sia richiesta una massiccia scalabilità e di conseguenza l'ottimizzazione degli accessi alle basi dati di sistema.
Rispetto ad ISAPI ed NSAPI, pur rappresentando una estensione al web server, mediante il meccanismo delle eccezioni risolvono a priori tutti gli errori che potrebbero causare la terminazione prematura del sistema.
Rispetto ad ASP, Servlet e JavaServer Pages separano completamente le logiche di business dalle logiche di presentazione dotando il programmatore di un ambiente semplice da modificare o mantenere.


http://www.freeonline.org/guide/javalibro_dtml

SU




Sistema ad eventi


Dispatcher


In un sistema ad eventi il ruolo fondamentale è svolto dal dispatcher il quale riceve i messaggi da una moltitudine di produttori e li re-invia a più destinatari.

I compiti principali che deve svolgere il dispatcher sono i seguenti:





















MSH attributes – HL7 v 2.4

SEQ

LEN

DT

OPT

RP/#

TBL#

ITEM #

ELEMENT NAME

1

1

ST

R



00001

Field Separator

2

4

ST

R



00002

Encoding Characters

3

180

HD

O



00003

Sending Application

4

180

HD

O



00004

Sending Facility

5

180

HD

O



00005

Receiving Application

6

180

HD

O



00006

Receiving Facility

7

26

TS

O



00007

Date/Time Of Message

8

40

ST

O



00008

Security

9

7

CM

R



00009

Message Type

10

20

ST

R



00010

Message Control ID

11

3

PT

R



00011

Processing ID

12

8

ID

R


0104

00012

Version ID

13

15

NM

O



00013

Sequence Number

14

180

ST

O



00014

Continuation Pointer

15

2

ID

O


0155

00015

Accept Acknowledgment Type

16

2

ID

O


0155

00016

Application Acknowledgment Type

17

2

ID

O



00017

Country Code

18

6

ID

O

Y/3

0211

00692

Character Set

19

60

CE

O



00693

Principal Language Of Message


Nella tabella sopra sono riportati tutti gli attributi del segmento MSH dei vari messaggi HL7. Questo segmento deve essere inserito nell'Header del messaggio in quanto contiene tutti i dati necessari per il routing del messaggio stesso.



Codice JAVA

SU

Web Service





Servlet1.java




import classi_varie.fil_writ;



import classi_varie.db1;

import java.sql.SQLException;



import javax.servlet.*;

import javax.servlet.http.*;

import java.io.*;

import java.net.*;


/**

*

* @author davide

*/


public class Servlet1 extends HttpServlet {

private static String message = "Error during Servlet processing";

public void doPost(HttpServletRequest req, HttpServletResponse resp) {

try {

int len = req.getContentLength();

byte[] input = new byte[len];

ServletInputStream sin = req.getInputStream();

int c, count = 0;

while ((c = sin.read(input, count, input.length-count)) != -1) {

count +=c;

}

sin.close();

String inString = new String(input);

int index = inString.indexOf("=");

if (index == -1) {

resp.setStatus(HttpServletResponse.SC_BAD_REQUEST);

resp.getWriter().print(message);

resp.getWriter().close();

return;

}

String value = inString.substring(index + 1);

//Decripta inString

//decode application/x-www-form-urlencoded string

String decodedString = URLDecoder.decode(value, "UTF-8");

fil_writ.addLineToFile("/home/davide/Documenti/progetto_s_e/sorgenti/elenco.txt", decodedString);

fil_writ.create_xml(decodedString, "/home/davide/Documenti/progetto_s_e/sorgenti/temporaney.xml");

String tipo=null;

//estrai tipo da inString;

int beg_seg = decodedString.indexOf("EVN");

String tipo1=value.substring(beg_seg+8);

int end_seg=tipo1.lastIndexOf("EVN");

tipo=tipo1.substring(0, end_seg-6);


//verifica se estra tipo

fil_writ.addLineToFile("/home/davide/Documenti/progetto_s_e/sorgenti/messaggi_ADT.txt", tipo);


String[] Lista_destinatari=null;


int errori0=0;

try {

Lista_destinatari=db1.main(tipo);//"root", "260885", tipo);

} catch (ClassNotFoundException ex) {

//Logger.getLogger(Servlet1.class.getName()).log(Level.SEVERE, null, ex);

errori0=1;

} catch (SQLException ex) {

//Logger.getLogger(Servlet1.class.getName()).log(Level.SEVERE, null, ex);

errori0=1;

}

int errori1=0;


//test per vedere se dal database scappa qualcosa - OK

/*int indice21=Lista_destinatari.length;

String indice33="0";

if (indice21>0){

indice33="1";

}

fil_writ.addLineToFile("/home/davide/Documenti/progetto_s_e/sorgenti/messaggi_ADT.txt", indice33);*/




//Verifica se il messaggio è conforme all'XSD

//errori1=XsdShemaValidator.main(tipo+".xsd", "/home/davide/Documenti/progetto_s_e/sorgenti/temporaney.xml");




//Prepara la risposta

int errori2=errori0+errori1;

//vediamo se ci sono errori - OK no errori

/*String indice33="0";

if (errori2>0){

indice33="1";

}

fil_writ.addLineToFile("/home/davide/Documenti/progetto_s_e/sorgenti/messaggi_ADT.txt", indice33);*/


// set the response code and write the response data


resp.setStatus(HttpServletResponse.SC_OK);

OutputStreamWriter writer = new OutputStreamWriter(resp.getOutputStream());

if(errori2>0){

String risposta="messaggio non conforme xsd";

writer.write(risposta);

//test per vedere se entra qui - OK non entra

//fil_writ.addLineToFile("/home/davide/Documenti/progetto_s_e/sorgenti/messaggi_ADT.txt", risposta);


}

else{

String risposta = "il messaggio da te inviato:"+decodedString+"è stato ricevuto e processato";

writer.write(risposta);

if(Lista_destinatari!=null){

int indice1=Lista_destinatari.length;

//Test per vedere se arriva qui - OK ci arriva

//fil_writ.addLineToFile(/*"messaggi_"+tipo+".txt"*/"/home/davide/Documenti/progetto_s_e/sorgenti/messaggi_ADT.txt", decodedString+"|"+indice1);

while(indice1!=0){

fil_writ.addLineToFile(/*"messaggi_"+tipo+".txt"*/"/home/davide/Documenti/progetto_s_e/sorgenti/messaggi_"+tipo+".txt", decodedString+"|"+indice1);//Lista_destinatari[indice1]+"|");//aggiungi ad un file messaggio e indirizzi[i] separati da | e con in fondo |, questo file sarà usato poi dal pacchetto coda

indice1--;

}

}}

writer.flush();

writer.close();

} catch (IOException e) {

try{

resp.setStatus(HttpServletResponse.SC_BAD_REQUEST);

resp.getWriter().print(e.getMessage());

resp.getWriter().close();

} catch (IOException ioe) {

}

}

} // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">

/**

* Handles the HTTP <code>GET</code> method.

* @param request servlet request

* @param response servlet response

* @throws ServletException if a servlet-specific error occurs

* @throws IOException if an I/O error occurs

*/




}

FileReaderTest.java


package classi_varie;


/**

*

* @author davide

*/

import java.io.*;


class FileReadTest {


public static void main (String[] args) {

FileReadTest f = new FileReadTest();

//args[0] contiene il nome del file dei messaggi, args[1] contiene il nome del file che contiene messaggi e indirizzi separati da | e terminanti con | a cui in prima istanza non ho potuto inviare, args[2] il tipo di quell'elenco di messaggi

//String nome_file = args[0];

String nome_file="/home/davide/Documenti/progetto_s_e/sorgenti/ciao.txt";

f.readMyFile(nome_file);

String[] righe_messaggi=f.readMyFile(args[0]);

String[] righe_mes_indirizzi= f.readMyFile(args[1]);

String[] indirizzi_a_cui_inviare=null;// = interroga database per rilevare tutti i destinatari interessati al tipo di evento args[2]

invia(righe_messaggi, indirizzi_a_cui_inviare);

ritenta(righe_mes_indirizzi);

}


String[] readMyFile(String nome_file) {


DataInputStream dis = null;

String record = null;

int recCount = 0;

String[] righe;

righe = new String[1000];


try {


File f = new File(nome_file);

FileInputStream fis = new FileInputStream(f);

BufferedInputStream bis = new BufferedInputStream(fis);

dis = new DataInputStream(bis);



while ( (record=dis.readLine()) != null ) {

recCount++;

System.out.println(recCount + ": " + record);

righe[recCount]=record;

}

System.out.println(righe[2]);


} catch (IOException e) {

// catch io errors from FileInputStream or readLine()

System.out.println("Uh oh, got an IOException error!" + e.getMessage());


} finally {

// if the file opened okay, make sure we close it

if (dis != null) {

try {

dis.close();

} catch (IOException ioe) {

}

}

}


return righe;

}


static void invia(String[] righe, String[] indirizzi){//righe contiene un messaggio per ogni riga, indirizzi un indirizzo a cui inviare per ogni riga

String provvisoria;

int i1=righe.length;

int i2=indirizzi.length;

while (i1>0){

provvisoria = righe[i1];

while (i2>0){

//Faccio il ReachableTest dell'indirizzo

//if(ritornoric!=null){

//invia righe[i1] a indirizzi[i2]}

//else{

//aggiungi ad un file righe[i1] e indirizzi[i2] separati da | e con in fondo |

//i2--

//}


}

i1--;

}

}


static void ritenta(String[] righe){//righe contiene un messaggio e l'indirizzo a cui inviarlo per ogni riga

String provvisoria;

int i1=righe.length;


while (i1>0){

int beg_seg = righe[i1].indexOf("|");

String messaggio=righe[i1].substring(0,beg_seg-1);

int end_string=righe[i1].lastIndexOf("|");

String indirizzo=righe[i1].substring(beg_seg+1,end_string-1);

//Faccio il ReachableTest dell'indirizzo

//if(ritornoric!=null){

//invia righe[i1] a indirizzi[i2]}

//else{

//aggiungi ad un file righe[i1] e indirizzi[i2] separati da | e con in fondo |

i1--;

}

i1--;

}

}



db1.java


package classi_varie;


import com.mysql.jdbc.Connection;

import com.mysql.jdbc.Statement;

import java.sql.DriverManager;

import java.sql.ResultSet;

import java.sql.SQLException;



/**

*

* @author davide

*/

public class db1 {


public static String[] main(String evento) throws ClassNotFoundException, SQLException{

System.out.println("Copyright 2004, R.G.Baldwin");


String nome_utente="root";

String password="260885";

evento="ADT";

String[] risultato1 = null;

try {

Statement stmt;


//Register the JDBC driver for MySQL.

Class.forName("com.mysql.jdbc.Driver");


//Define URL of database server for

// database named mysql on the localhost

// with the default port number 3306.

String url ="jdbc:mysql://localhost:3306/dispatcher";


//Get a connection to the database for a

// user named root with a blank password.

// This user is the default administrator

// having full privileges to do anything.

Connection con = (Connection) DriverManager.getConnection(url,nome_utente, password);


//Display URL and connection information

System.out.println("URL: " + url);

System.out.println("Connection: " + con);



//Get a Statement object

stmt = (Statement) con.createStatement();

ResultSet ris = stmt.executeQuery("SELECT * FROM tipi_messaggi"); /*WHERE tipi_messaggi.name='" + evento + "'");*/

ris.last();

int lunghezza_risultato=(int)ris.getInt("id");

String[] risultato=new String[lunghezza_risultato];

ris.first();

int indice=0;

ResultSet ris2 = stmt.executeQuery("SELECT * FROM tipi_messaggi"); /*WHERE tipi_messaggi.name='" + evento + "'");*/

while (ris2.next()) {


risultato[indice] = ris2.getString("id");//indirizzo destinatario

System.out.println(risultato[indice]);

}


con.close();

risultato1=risultato;

}catch( Exception e ) {

e.printStackTrace();

}//end catch

return risultato1;

}//end main

}//end class Jdbc12

fil_writ.java


package classi_varie;


/**

*

* @author davide

*/

import java.io.BufferedReader;

import java.io.File;

import java.io.FileNotFoundException;

import java.io.FileReader;

import java.io.FileWriter;

import java.io.IOException;

import java.io.PrintWriter;


/**

*

* @author davide

*/

public class fil_writ {



static public void addLineToFile(String file, String lineToadd) {


try {


File inFile = new File(file);


if (!inFile.isFile()) {

System.out.println("Parameter is not an existing file");

return;

}


//Construct the new file that will later be renamed to the original filename.

File tempFile = new File(inFile.getAbsolutePath() + ".tmp");


BufferedReader br = new BufferedReader(new FileReader(file));

PrintWriter pw = new PrintWriter(new FileWriter(tempFile));


String line = null;


//Read from the original file and write to the new

//unless content matches data to be removed.

while ((line = br.readLine()) != null) {


pw.println(line);

pw.flush();

}


pw.println(lineToadd);

pw.close();

br.close();


//Delete the original file

if (!inFile.delete()) {

System.out.println("Could not delete file");

return;

}


//Rename the new file to the filename the original file had.

if (!tempFile.renameTo(inFile))

System.out.println("Could not rename file");


}

catch (FileNotFoundException ex) {

ex.printStackTrace();

}

catch (IOException ex) {

ex.printStackTrace();

}

}


static public void create_xml(String text, String file){

try {


File inFile = new File(file);


if (!inFile.isFile()) {

System.out.println("Parameter is not an existing file");

return;

}


PrintWriter pw = new PrintWriter(new FileWriter(file));




pw.println(text);



pw.close();


}

catch (FileNotFoundException ex) {

ex.printStackTrace();

}

catch (IOException ex) {

ex.printStackTrace();

}

}}

XsdSchemaValidator.java


package classi_varie;


/**

*

* @author davide

*/

import javax.xml.validation.SchemaFactory;

import javax.xml.validation.Schema;

import javax.xml.XMLConstants;

import javax.xml.transform.sax.SAXSource;

import org.xml.sax.InputSource;

import javax.xml.validation.Validator;

import java.io.*;

import org.xml.sax.SAXException;

import org.xml.sax.SAXParseException;

import org.xml.sax.ErrorHandler;


public class XsdShemaValidator {

private static int errorCount = 0;

int errori=0;

public static int main(String file_xsd, String file_xml) {

/*if (a.length<2) {

System.out.println("Usage:");

System.out.println("java XsdSchemaValidator schema_file_name "

+ "xml_file_name");

} else {*/


String schemaName = file_xsd;

String xmlName = file_xml;

Schema schema = loadSchema(schemaName);

validateXml(schema, xmlName);

//}

return errorCount;

}


public static void validateXml(Schema schema, String xmlName) {

try {

// creating a Validator instance

Validator validator = schema.newValidator();


// setting my own error handler

validator.setErrorHandler(new MyErrorHandler());


// preparing the XML file as a SAX source

SAXSource source = new SAXSource(

new InputSource(new java.io.FileInputStream(xmlName)));


// validating the SAX source against the schema

validator.validate(source);

System.out.println();

if (errorCount>0) {

System.out.println("Failed with errors: "+errorCount);

} else {

System.out.println("Passed.");

}


} catch (Exception e) {

// catching all validation exceptions

System.out.println();

System.out.println(e.toString());


}

}

public static Schema loadSchema(String name) {

Schema schema = null;

try {

String language = XMLConstants.W3C_XML_SCHEMA_NS_URI;

SchemaFactory factory = SchemaFactory.newInstance(language);

schema = factory.newSchema(new File(name));

} catch (Exception e) {

System.out.println(e.toString());

}

return schema;

}

private static class MyErrorHandler implements ErrorHandler {

public void warning(SAXParseException e) throws SAXException {

System.out.println("Warning: ");

printException(e);

}

public void error(SAXParseException e) throws SAXException {

System.out.println("Error: ");

printException(e);

}

public void fatalError(SAXParseException e) throws SAXException {

System.out.println("Fattal error: ");

printException(e);

}

private void printException(SAXParseException e) {

errorCount++;

System.out.println(" Line number: "+e.getLineNumber());

System.out.println(" Column number: "+e.getColumnNumber());

System.out.println(" Message: "+e.getMessage());

System.out.println();

}

}

}


SU

Gestore coda





ReachableTest.java


package coda;


/**

*

* @author davide

*/

import java.io.*;

import java.net.*;


public class ReachableTest {

public static boolean main(String indirizzo) {

boolean risultato=true;

try {

InetAddress address = InetAddress.getByName(indirizzo);

System.out.println("Name: " + address.getHostName());

System.out.println("Addr: " + address.getHostAddress());

System.out.println("Reach: " + address.isReachable(3000));

risultato=true;

}

catch (UnknownHostException e) {

System.err.println("Unable to lookup"+indirizzo);

risultato=false;

}

catch (IOException e) {

System.err.println("Unable to reach"+indirizzo);

risultato=false;

}

return risultato;

}

}

coda.java


package coda;


/**

*

* @author davide

*/


import java.io.*;

import java.lang.String;

import java.util.logging.Level;

import java.util.logging.Logger;


public class coda {


/*public static void main (String[] args) {

FileReadTest f = new FileReadTest();

//args[0] contiene il nome del file dei messaggi, args[1] contiene il nome del file che contiene messaggi e indirizzi separati da | e terminanti con | a cui in prima istanza non ho potuto inviare, args[2] il tipo di quell'elenco di messaggi

//String nome_file = args[0];

String nome_file="/home/davide/Documenti/progetto_s_e/sorgenti/ciao.txt";

f.readMyFile(nome_file);

String[] righe_messaggi=f.readMyFile(args[0]);

String[] righe_mes_indirizzi= f.readMyFile(args[1]);

String[] indirizzi_a_cui_inviare=null;// = interroga database per rilevare tutti i destinatari interessati al tipo di evento args[2]

invia(righe_messaggi, indirizzi_a_cui_inviare);

ritenta(righe_mes_indirizzi);

}*/


public static String[] readMyFile(String file_coda) {


DataInputStream dis = null;

String record = null;

int recCount = 0;

String[] righe;

righe = new String[1000];


try {


File f = new File(file_coda);

FileInputStream fis = new FileInputStream(f);

BufferedInputStream bis = new BufferedInputStream(fis);

dis = new DataInputStream(bis);




while ( (record=dis.readLine()) != null ) {

recCount++;

System.out.println(recCount + ": " + record);

righe[recCount]=record;

}


} catch (IOException e) {

// catch io errors from FileInputStream or readLine()

System.out.println("Uh oh, got an IOException error!" + e.getMessage());


} finally {

// if the file opened okay, make sure we close it

if (dis != null) {

try {

dis.close();

} catch (IOException ioe) {

}

}

}


return righe;

}


public static void ritenta(){//righe contiene un messaggio e l'indirizzo a cui inviarlo per ogni riga

String[] righe = readMyFile("coda.txt");

int i1=righe.length;


while (i1>0){

int beg_seg = righe[i1].indexOf("|");

String messaggio=righe[i1].substring(0,beg_seg-1);

int end_string=righe[i1].lastIndexOf("|");

String indirizzo=righe[i1].substring(beg_seg+1,end_string-1);

boolean risultato=ReachableTest.main(indirizzo);

if(risultato=true){

try {

send.main(messaggio, indirizzo);

} catch (Exception ex) {

Logger.getLogger(coda.class.getName()).log(Level.SEVERE, null, ex);

fil_writ.addLineToFile("coda.txt", messaggio+"|"+indirizzo+"|");//aggiungi ad un file messaggio e indirizzi[i] separati da | e con in fondo |

}

}

else{

fil_writ.addLineToFile("coda.txt", messaggio+"|"+indirizzo+"|");//aggiungi ad un file messaggio e indirizzi[i] separati da | e con in fondo |


}

i1--;

}

}


public static void invia(){//righe contiene un messaggio per ogni riga, indirizzi un indirizzo a cui inviare per ogni riga

String[] righe = readMyFile("messaggi_ADT.txt");

int i1=righe.length;


while (i1>0){

int beg_seg = righe[i1].indexOf("|");

String messaggio=righe[i1].substring(0,beg_seg-1);

int end_string=righe[i1].lastIndexOf("|");

String indirizzo=righe[i1].substring(beg_seg+1,end_string-1);

boolean risultato=ReachableTest.main(indirizzo);

if(risultato=true){

try {

send.main(messaggio, indirizzo);

} catch (Exception ex) {

Logger.getLogger(coda.class.getName()).log(Level.SEVERE, null, ex);

fil_writ.addLineToFile("coda.txt", messaggio+"|"+indirizzo+"|");//aggiungi ad un file messaggio e indirizzi[i] separati da | e con in fondo |

}

}

else{

fil_writ.addLineToFile("coda.txt", messaggio+"|"+indirizzo+"|");//aggiungi ad un file messaggio e indirizzi[i] separati da | e con in fondo |


}

i1--;

}

}


}


fil_writ.java


package coda;


/**

*

* @author davide

*/

import java.io.BufferedReader;

import java.io.File;

import java.io.FileNotFoundException;

import java.io.FileReader;

import java.io.FileWriter;

import java.io.IOException;

import java.io.PrintWriter;


/**

*

* @author davide

*/

public class fil_writ {



static public void addLineToFile(String file, String lineToadd) {


try {


File inFile = new File(file);


if (!inFile.isFile()) {

System.out.println("Parameter is not an existing file");

return;

}


//Construct the new file that will later be renamed to the original filename.

File tempFile = new File(inFile.getAbsolutePath() + ".tmp");


BufferedReader br = new BufferedReader(new FileReader(file));

PrintWriter pw = new PrintWriter(new FileWriter(tempFile));


String line = null;


//Read from the original file and write to the new

//unless content matches data to be removed.

while ((line = br.readLine()) != null) {


pw.println(line);

pw.flush();

}


pw.println(lineToadd);

pw.close();

br.close();


//Delete the original file

if (!inFile.delete()) {

System.out.println("Could not delete file");

return;

}


//Rename the new file to the filename the original file had.

if (!tempFile.renameTo(inFile))

System.out.println("Could not rename file");


}

catch (FileNotFoundException ex) {

ex.printStackTrace();

}

catch (IOException ex) {

ex.printStackTrace();

}

}


static public void create_xml(String text, String file){

try {


File inFile = new File(file);


if (!inFile.isFile()) {

System.out.println("Parameter is not an existing file");

return;

}


PrintWriter pw = new PrintWriter(new FileWriter(file));




pw.println(text);



pw.close();


}

catch (FileNotFoundException ex) {

ex.printStackTrace();

}

catch (IOException ex) {

ex.printStackTrace();

}

}}

send.java


package coda;


import java.io.BufferedReader;

import java.io.InputStreamReader;

import java.io.OutputStreamWriter;

import java.net.URL;

import java.net.URLConnection;

import java.net.URLEncoder;


/**

*

* @author davide

*/

public class send {

public static void main(String messaggio, String indirizzo) throws Exception {


/*if (args.length != 2) {

System.err.println("Usage: java Reverse " +

"http://localhost:8081/http_service/Servlet1" +

" string_to_reverse");

System.exit(1);

}*/

//String messaggio_da_inviare="davide sei forte";

String stringToReverse = URLEncoder.encode(messaggio, "UTF-8");


URL url = new URL(indirizzo);//args[0]);"http://localhost:8081/http_service/Servlet1"

URLConnection connection = url.openConnection();

connection.setDoOutput(true);


OutputStreamWriter out = new OutputStreamWriter(

connection.getOutputStream());

out.write("string=" + stringToReverse);

out.close();


BufferedReader in = new BufferedReader(

new InputStreamReader(

connection.getInputStream()));


String decodedString;


while ((decodedString = in.readLine()) != null) {

System.out.println(decodedString);

}

in.close();

}

}


SU


Contatto: dew85@tiscali.it

SU