Per
l'impaziente...
Potete
provare subito l'esempio di questa volta: scaricate il sorgente da qui
e lanciate "remot.bat", l'esempio verrà compilato e lanciato. Vedrete
che si apriranno due finestre (se tutto è andato bene :-) aggiuntive
(rmiregistry e il server), mentre nella finestra da dove avete lanciato
il ".bat" vedrete il contenuto di due directory e di un file.
Scopo dell'esempio
Per
sperimentare un po' con RMI ho deciso di inventarmi un "proxy remoto" (parziale)
di un oggetto File (proprio il java.io.File). Un RemoteFile che mi permetta
di effettuare alcune operazioni sul filesystem del server via rete.
Partiamo
col vederne le specifiche (UML naturalmente):
L'oggetto
RemoteFile (è l'oggetto remoto) pubblica via RMI alcune operazioni
che poi effettua sull'oggetto File a cui è stato associato in fase
di creazione (vedere i costruttori).
Le
operazioni effettuabili sono poche, data la necessità didattica
dell'esempio, però nulla vieta di rendere più corposa la
classe RemoteFile. Ecco i dettagli:
public
String[] list()
serve
a ottenere l'elenco dei contenuti (directory/files) del RemoteFile corrente
public
RemoteFileI newFile(String nomeFile)
FACTORY
METHOD (vedere articolo di Giovanni)
serve
a creare un nuovo oggetto remoto (che quindi resta sul server) senza passare
per bind/lookup
public
RemoteFileI getParent()
ritorna
un nuovo RemoteFile che punta alla directory superiore rispetto al corrente;
usa newFile(...)
public
InMemoryFile getContent()
ritorna
una immagine (in memoria) del contenuto del file rappresentato
La classe
InMemoryFile serve solo come wrapper di un array di byte, per poter spedire
l'intero contenuto del file puntato da RemoteFile (attenzione a spedire
file grossi!). Di per sè InMemoryFile NON è un vero proxy
dato che contiene una copia del contenuto del file, se modificate la copia
il file originario rimane invariato.
Implementazione
La
cosa interessante e divertente è che RemoteFile non ha quasi nulla
al suo interno: delega pressochè tutte le sue funzioni al File che
rappresenta.
Ad
esempio guardiamo il metodo getParent(), esso non fa altro che chiedere
il parent al File e costruirgli attorno un nuovo RemoteFile:
public RemoteFileI getParent() throws RemoteException{
return newFile(file.getParent());
}
Idem
per il metodo list(), che è ancora più banale.
Suggerimenti
Si
può pensare di aggiungere il simmetrico del metodo getContent(),
un qualche metodo che accetti (invece di fornire) un InMemoryFile e lo
salvi su disco (o da qualche altra parte), qualcosa di questo tipo:
public void takeContent(InMemoryFile
contentToWrite)
throws RemoteException{
System.out.println("Richiesto salvataggio su " + this);
FileOutputStream out=new FileOutputStream(this);
out.write(contentToWrite.content);
}
(più
il try&catch naturalmente)
Per
gli amanti dei pattern, la classe InMemoryFile sostanzialmente è
uno State mentre il RemoteFile in questo caso farebbe le veci del CareTaker...
:-)
Volendo
si potrebbero aggiungere anche dei metodi read() e write() per permettere
(con molta cautela) l'accesso diretto al File puntato.
Naturalmente
grande cautela in realtà va usata in tutte quelle situazioni in
cui (potenzialmente) più clienti accedono alla stessa risorsa, per
di più in scrittura.
|