You are on page 1of 19

Java RMI Accesso ad oggetti remoti

(Remote Method Invocation) In Java non sono possibili riferimenti remoti

RPC in JAVA C1 instance


CLASS server S1
S1 instance
Le RMI introducono la possibilità di richiedere S1 instance

esecuzione di metodi remoti in JAVA integrando il state

operations
tutto con il paradigma OO

Definizioni e generalità Supporto di INTEGRAZIONE


per la DISTRIBUZIONE
Insieme di politiche e meccanismi che permettono ad
un’applicazione Java in esecuzione su una macchina
di invocare i metodi di un oggetto di una applicazione ma si possono costruire con RMI
Java in esecuzione su una macchina remota
Remote Method Invocation
Viene creato localmente solo il riferimento ad due proxy,
un oggetto remoto, che è invece effettivamente stub dalla parte del cliente,
attivo su un nodo remoto skeleton dalla parte del servitore
Un programma cliente invoca i metodi attraverso
questo riferimento locale C1 instance

S1 instance

Unico ambiente di lavoro


come conseguenza del linguaggio Java ma
Eterogeneità di ambienti

C1 Stub S1 Skeleton

CLIENT node SERVER node

Reti di calcolatori, Java RMI - 1 Reti di calcolatori, Java RMI - 2


Architettura Caratteristiche

Registry Modello a oggetti distribuito


Client Program Server Program
Nel modello ad oggetti distribuito di Java un oggetto
remoto consiste in:
Stubs Skeletons - un oggetto i cui metodi sono invocabili da un'altra
RMI System

JVM, potenzialmente in esecuzione su un host


Remote Reference Layer Remote Reference Layer differente
Transport Layer - un oggetto descritto tramite interfacce remote che
dichiarano i metodi accessibili da remoto

Stub: proxy locale su cui vengono fatte le invocazioni


destinate all’oggetto remoto
Skeleton: entità remota che riceve le invocazioni fatte sullo Chiamata locale vs. chiamata remota
stub e le realizza effettuando le corrispondenti chiamate sul Il cliente invoca un metodo di un oggetto non locale
server
Sintassi: uguale => trasparenza
Registry: servizio di nomi che consente al server di Chiamata sincrona
pubblicare un servizio e al client di recuperarne il proxy
Semantica: diversa
Remote Reference Layer: Chiamate locali: affidabilità ≈ 100%
- fornisce il supporto alle chiamate inoltrate dallo stub
- localizza il server RMI relativo all’oggetto remoto richiesto
Chiamate remote: uso di comunicazione
Transport Layer: definisce e supporta la semantica possibilità di fallimento
dell’invocazione e della comunicazione, gestisce le semantica “at most once” con uso TCP
connessioni (TCP/IP, timeout) e le trasmissioni (sequenziali,
serializzate), usando un protocollo proprietario Server remoto come locale:
Ogni chiamata esegue in modo indipendente e
parallelo (?)
Reti di calcolatori, Java RMI - 3 Reti di calcolatori, Java RMI - 4
SERVIZIO REMOTO RMI Uso di RMI
Interfacce e Implementazione
Per sviluppare un’applicazione distribuita usando RMI
Separazione tra si deve:
definizione del comportamento => interfacce
1. Definire interfacce e implementazioni dei server
implementazione del comportamento => classi utilizzabili in remoto (implementazioni?)
Per realizzare componenti utilizzabili in remoto: 2. Compilare le classi (con javac) e generare stub e
skeleton (con rmic) delle classi utilizzabili in
remoto
1. definizione del comportamento Ö
metodi disponibili in interfaccia che 3. Pubblicare il servizio
- estende java.rmi.Remote e - attivare il registry
- propaga java.rmi.RemoteException - registrare il servizio
(il server deve fare una bind sul registry)
2. implementare comportamento Ö 4. Il cliente deve ottenere il riferimento all’oggetto
il server specificato in una classe che remoto tramite il name service, facendo una
- implementa l’interfaccia definita lookup sul registry
- estende
java.rmi.UnicastRemoteObject
A questo punto l’interazione tra il cliente e il server
può procedere

N.B.: questa è una descrizione di base, dettagli sul


registry e sul caricamento dinamico delle classi
saranno dati in seguito

Reti di calcolatori, Java RMI - 5 Reti di calcolatori, Java RMI - 6


Esempio: Implementazione del Server
servizio di echo remoto
public class EchoRMIServer
extends java.rmi.server.UnicastRemoteObject
implements EchoInterface{

// Costruttore
Definizione dell’interfaccia del servizio public EchoRMIServer()
throws java.rmi.RemoteException
{ super(); }
public interface EchoInterface
extends java.rmi.Remote // Implementazione del metodo remoto
{ dichiarato nell'interfaccia
public String getEcho(String echo)
String getEcho(String echo) throws java.rmi.RemoteException
throws java.rmi.RemoteException; { return echo; }
}
public static void main(String[] args){
// Registrazione del servizio
try
{
EchoRMIServer serverRMI =
new EchoRMIServer();
Naming.rebind("EchoService", serverRMI);
}
catch (Exception e)
{e.printStackTrace(); System.exit(1); }
}
}

Reti di calcolatori, Java RMI - 7 Reti di calcolatori, Java RMI - 8


Implementazione del Client Compilazione
public class EchoRMIClient
{ javac EchoInterface.java
// Avvio del Client RMI EchoRMIClient.java
public static void main(String[] args) EchoRMIServer.java
{
BufferedReader stdIn=
new BufferedReader(
new InputStreamReader(System.in)); Creazione dello Stub e dello Skeleton
try
{ Con il compilatore RMI (con opzione –vcompat in
// Connessione al servizio RMI remoto Java 1.5):
EchoInterface serverRMI = (EchoInterface) rmic [-vcompat] EchoRMIServer
java.rmi.Naming.lookup("EchoService");
// Notare l’uso di cast
Che genera i file:
// Interazione con l'utente EchoRMIServer_Stub.class
String message, echo; EchoRMIServer_Skel.class
System.out.print("Messaggio? ");
message = stdIn.readLine();
Esecuzione
// Richiesta del servizio remoto
echo = serverRMI.getEcho(message); 1. Avviamento del registry:
System.out.println("Echo: "+echo+"\n");
} rmiregistry
catch (Exception e)
{ e.printStackTrace(); System.exit(1); } 2. Avviamento del server:
} java EchoRMIServer
}
3. Avviamento del client:
java EchoRMIClient

Reti di calcolatori, Java RMI - 9 Reti di calcolatori, Java RMI - 10


Passaggio di parametri Serializzazione
Trattamento dei parametri tra pari
Tipo Metodo Locale Metodo Remoto
Tipi primitivi Per valore Per valore Marshalling: processo di codifica degli argomenti e
Oggetti Per riferimento Per valore dei risultati per la trasmissione
(deep copy) Unmarshalling: processo inverso di decodifica di
Oggetti Remoti Per riferimento Per riferimento argomenti e risultati ricevuti
Esportati remoto
In Java questo problema è risolto attraverso la
Shallow Copy vs Deep Copy semplice serializzazione, fatta in maniera trasparente
dal supporto (copia dei dati trasformati in una
Passaggio per valore => Serializable Objects sequenza e un messaggio e trasferiti tra le JVM)
Passaggio per riferimento => Remote Objects
Serializzazione: trasformazione di oggetti
Serializable Objects complessi in semplici sequenze di byte
Oggetti la cui locazione non è rilevante per lo stato
sono passati per valore: ne viene serializzata => metodo writeObject()
l’istanza che sarà deserializzata a destinazione per su uno stream di output
crearne una copia locale. Deserializzazione: decodifica di una sequenza di
byte e costruzione di una copia dell’oggetto
Remote Objects originale
Oggetti la cui funzione è strettamente legata alla
località in cui eseguono (server) => metodo readObject()
sono passati per riferimento: ne viene serializzato da uno stream di input
lo stub, creato automaticamente dal proxy (stub o
skeleton) su cui viene fatta la chiamata in cui Utilizzo:
compaiono come parametri - storage
- trasmissione (parametri e valori di ritorno in RMI)

Reti di calcolatori, Java RMI - 11 Reti di calcolatori, Java RMI - 12


Interazione con stream per TX/RX Esempio
Esempio di storage
Riprendendo il server di echo
Record record = new Record();
FileOutputStream fos = new
FileOutputStream(“data.ser”); Ö messaggio come oggetto anziché come stringa
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(record);

public class Message implements Serializable


FileInputStream fis = new {
FileInputStream(“data.ser”);
ObjectInputStream ois = new ObjectInputStream(fis); String content;
record = (Record)ois.readObject();
// … altri eventuali campi

Si possono serializzare soltanto istanze di oggetti public Message(String msg)


{
serializzabili, ovvero che: content=msg;
- implementano l’interfaccia Serializable }
- contengono esclusivamente oggetti (o riferimenti public String toString()
a oggetti) serializzabili {
return content;
}
NOTA BENE:
}
NON viene trasferito l’oggetto vero e proprio ma solo
le informazioni che caratterizzano l’istanza
=> no metodi, no costanti,
no variabili static, no variabili transient
Al momento della deserializzazione sarà ricreata una
copia dell’istanza “trasmessa” usando il .class (che
deve quindi essere accessibile!!!) dell’oggetto e le
informazioni ricevute.

Reti di calcolatori, Java RMI - 13 Reti di calcolatori, Java RMI - 14


Stub e Skeleton Stub
Stub e Skeleton garantiscono una parziale trasparenza Estende java.rmi.server.RemoteStub
e sono oggetti generati dal compilatore RMI che
gestiscono il supporto RMI via Implementa java.rmi.Remote
InterfacciaRemotaServer
serializzazione/deserializzazione e (es. EchoInterface)
comunicazione tra client e server
Realizza le chiamate ai metodi dell’interfaccia remota
Procedura di comunicazione: del server usando il metodo invoke(…)
1. il client ottiene un’istanza dello stub di java.rmi.server.RemoteRef
2. il client chiama metodi sullo stub
3. lo stub: public final class EchoRMIServer_Stub
extends java.rmi.server.RemoteStub
- crea una connessione con lo skeleton implements EchoInterface, java.rmi.Remote
(o ne usa una già esistente) { …
// implementazione di getEcho
- fa la serializzazione delle informazioni per la public Message getEcho(Message message)
throws java.rmi.RemoteException
chiamata (id del metodo e argomenti) {
- invia le informazioni allo skeleton try
{ …
4. lo skeleton: // creazione della chiamata
java.rmi.server.RemoteCall remotecall =
- fa deserializzazione dei dati ricevuti super.ref.newCall(this, operations, 0,
- effettua la chiamata sull’oggetto che 0xca41fff3e3260b7aL);
implementa il server // serializzazione dei parametri
- fa serializzazione del valore di ritorno try
{
e invio allo allo stub ObjectOutput objectoutput =
remotecall.getOutputStream();
5. lo stub:
- fa deserializzazione del valore di ritorno e }
objectoutput.writeObject(message);

restituzione del risultato al client // cattura eccezioni di marshalling


Reti di calcolatori, Java RMI - 15 Reti di calcolatori, Java RMI - 16


Stub segue Skeleton
Implementa java.rmi.server.Skeleton
// invio della chiamata
super.ref.invoke(remotecall);
Inoltra le richieste al server usando il
// deserializzazione del valore di ritorno
metodo dispatch(…)
Message message1;
try public final class EchoRMIServer_Skel implements Skeleton
{ {
ObjectInput objectinput = …
remotecall.getInputStream(); public void dispatch(Remote remote,
message1 = RemoteCall remotecall, int opnum, long hash)
(Message)objectinput.readObject(); throws Exception
} {
// cattura eccezioni di unmarshalling // validazione e verifica di errori
… …
EchoRMIServer echormiserver = (EchoRMIServer)remote;
// segnalazione chiamata andata a buon fine switch(opnum)
finally {
{ case 0: // '\0'
super.ref.done(remotecall); Message message;
} try
{
// restituzione del risultato // deserializzazione dei parametri di invocazione
return message1; ObjectInput objectinput =
remotecall.getInputStream();
} message = (Message)objectinput.readObject();
// cattura varie eccezioni }
… catch(IOException ioexception1)
{
} throw new UnmarshalException("error
unmarshalling arguments", ioexception1);
… }
} catch(ClassNotFoundException classnotfoundexception)
{
throw new UnmarshalException("error ...”
unmarshalling arguments", classnotfoundexception);
}
finally
{
remotecall.releaseInputStream();
}

Reti di calcolatori, Java RMI - 17 Reti di calcolatori, Java RMI - 18


Skeleton segue Interazione Client/Server:
// effettiva invocazione del metodo sul server
Socket e Thread
Message message1 = echormiserver.getEcho(message);

try
{ Client
// serializzazione del valore di ritorno
ObjectOutput objectoutput =
remotecall.getResultStream(true); L’invocazione di un metodo remoto implica una connessione
objectoutput.writeObject(message1);
} TCP (Socket stream) con l’oggetto remoto
catch(IOException ioexception)
{
throw new MarshalException("error Condivisione delle connessioni tra la JVM client e la
marshalling return", ioexception); JVM server:
}
break;
richiesta di connessione per una stessa JVM
default:
throw new UnmarshalException("invalid ...");
- se c’è una connessione aperta Ö riuso
} - se non c’è una connessione aperta Ö nuova
}
… Al completamento di una operazione la connessione
} viene liberata e rimane attiva fino allo scadere di un
intervallo di timeout
Chi genera i thread che devono operare
sull’oggetto server, se non lo skeleton?
RMI permette a più thread clienti di accedere ad uno stesso
Questo si lega al fatto che skeleton e stub oggetto server gestendo in modo automatico la
concorrenza delle operazioni
sono generati non come sorgenti, ma come Ö l’implementazione del cliente non deve preoccuparsi
class?
In caso di richieste da parte della stessa JVM, il canale di
comunicazione unico può produrre effetti di
sequenzializzazione (era ciò che accadeva nelle prime
implementazioni)

Reti di calcolatori, Java RMI - 19 Reti di calcolatori, Java RMI - 20


Server RMI Registry
Dipende tutto dall’implementazione. Nel seguito
consideriamo una possibile e semplice implementazione
Localizzazione del servizio: un client in esecuzione
concorrente. su una macchina ha bisogno di localizzare un server a
cui vuole connettersi, che è in esecuzione su un’altra
L’esportazione di un oggetto remoto provoca la creazione di macchina. Tre possibili soluzioni:
• diversi thread per la gestione delle richieste (Server • Il client conosce staticamente dov’è il server
Socket)
• un thread che riceve le richieste (Listener Thread) • L’utente dice all’applicazione client dov’è il server
associati all’oggetto remoto
• Un servizio standard (naming service) in una
Condivisione delle server socket e dei listener: server in locazione ben nota, che il client conosce,
esecuzione nella stessa JVM possono condividere la porta funziona come sistema di nomi
d’ascolto (soluzione di default se non la specificano) e il
listener che ne gestisce le richieste Java RMI utilizza un naming service: RMI Registry

Ogni richiesta viene gestita da Mantiene un insieme di coppie {name, reference}


• un thread che esegue la richiesta (Server Thread) Name: stringa arbitraria non interpretata

Condivisione dei server thread: allocazione di un pool di Echo


thread; all’accettazione di una nuova richiesta un Server Name Reference Server
Thread viene estratto ed utilizzato.
E se i thread del pool vengono tutti allocati? Soluzioni Echo
possibili?
Daytime
Daytime
Server
In ogni caso: RMI permette a più thread di accedere ad Login
uno stesso oggetto server (gestione concorrente delle Login
richieste) Server
Ö l’implementazione dei metodi remoti
deve essere thread-safe Trasparenza alla locazione?!?

Reti di calcolatori, Java RMI - 21 Reti di calcolatori, Java RMI - 22


Operazioni Implementazione del Registry
Metodi della classe java.rmi.Naming: Il Registry è un server RMI
public
public
static
static
void bind(String name, Remote obj)
void rebind(String name, Remote obj)
Classe d’implementazione:
public static void unbind(String name) sun.rmi.registry.RegistryImpl
public static String[] list(String name)
public static Remote lookup(String name)
Interfaccia: java.rmi.registry.Registry
name -> combina la locazione del registry e il nome public interface Registry extends Remote {
logico del servizio, nel formato:
public static final int REGISTRY_PORT = 1099;

//registryHost:port/logical_name public Remote lookup(String name)


throws RemoteException, NotBoundException,
AccessException;
A default: public void bind(String name, Remote obj)
registryHost = macchina su cui esegue throws RemoteException, AlreadyBoundException,
AccessException;
il programma che invoca il metodo public static void rebind(String name, Remote obj)
port = 1099 throws RemoteException, AccessException;
public static void unbind(String name)
throws RemoteException, NotBoundException,
AccessException;
Il Registry è un server RMI public static String[] list(String name)
in esecuzione su registryHost throws RemoteException, AccessException;
in ascolto su port }

Ognuno di questi metodi crea una connessione Remote è il riferimento remoto


(socket) con il registry identificato da host e porta
Perchè usare anche la classe Naming?

Reti di calcolatori, Java RMI - 23 Reti di calcolatori, Java RMI - 24


BOOTSTRAP Uso del Registry

Problema di bootstrapping anche per localizzare il Due possibilità:


registry Ö uso delle classi Naming e LocateRegistry 1. Usare il programma rmiregistry di Sun, lanciato
specificando o meno la porta:
• Naming: metodi statici, no istanza
rmiregistry
• LocateRegistry implementa i metodi rmiregistry 10345
Ö istanza separata della JVM
public static Registry createRegistry(int port)
public static Registry createRegistry(int port,
Ö struttura e comportamento standard
RMIClientSocketFactory csf,
RMIServerSocketFactory ssf)
public static Registry getRegistry()
public static Registry getRegistry(int port)
public static Registry getRegistry(String host) 2. Creare all’interno del codice un proprio registry:
public static Registry getRegistry(String host,
int port) public static Registry createRegistry(int port)
public static Registry getRegistry(String host,
int port, RMIClientSocketFactory csf) Ö stessa istanza della JVM
Ö struttura e comportamento personalizzabile
(es. organizzazione gerarchica)

Soluzione al bootstrapping per il registry:


1. Naming.”metodo()” con host e porta

1. Invocazione di LocateRegistry.getRegistry() che


restituisce lo stub del registry
2. Invocazione di “metodo()” sullo stub

Reti di calcolatori, Java RMI - 25 Reti di calcolatori, Java RMI - 26


Sicurezza del registry Organizzazione gerarchica Registry
Problema: accedendo al registry Un registry è un server RMI
(individuabile interrogando tutte le porte di un host) => è possibile registrarlo in un altro registry
è possibile ridirigere per scopi maliziosi le chiamate ai
server RMI registrati Registry ourRegistry =
LocateRegistry.createRegistry(OUR_PORT);
(es. list()+rebind()) Registry preexistingRegistry =
LocateRegistry.getRegistry(1099);
Soluzione: preexixtingRegistry.rebind
(“secondary registry”, ourRegistry);
i metodi bind(), rebind() e unbind() sono invocabili
solo dall’host su cui è in esecuzione il registry Printer Registry
Ö Name Reference
non si accettano modifiche della struttura client/server Primary Registry
Postscript
da nodi esterni Pdf
...
Name Reference
Program Registry
Registro Stampanti Name Reference
Ö sull’host in cui vengono effettuate le chiamate
Antivirus
al registry deve essercene almeno uno in Registro Installazioni
IDE
esecuzione ... ...

...

Ma…
• Tutti i registry si trovano sulla stessa macchina
dove è attivato il primary registry
• Lato client devo gestire una duplice
interrogazione
• RMI registry non supporta in alcun modo la
negoziazione dei servizi

Reti di calcolatori, Java RMI - 27 Reti di calcolatori, Java RMI - 28


Distribuzione delle classi Classpath ed Esecuzione
In una applicazione RMI è necessario che siano Rmiregistry, server e client devono poter accedere
disponibili gli opportuni file .class nelle località che lo alle classi necessarie per l’esecuzione. Si presti quindi
richiedono particolare attenzione al direttorio dove vengono
(per l’esecuzione o per la deserializzazione) lanciati l’rmiregistry, il server e il client

In particolare, ipotizzando di avere tutti i file .class nel


Il Server deve poter accedere a: direttorio corrente (“.”), e di lanciare rmiregistry, client,
e server dal direttorio corrente, bisogna aggiungere al
• interfacce che definiscono il servizio CLASSPATH tale direttorio
• implementazione del servizio
• stub e skeleton delle classi di implementazione Sotto Linux: ciò è possibile aggiungendo nella propria
• altre classi utilizzate dal server directory HOME il file ".profile" (creandolo se
non esiste). In particolare, il file .profile deve
contenere le seguenti linee per aggiungere il
Il Client deve poter accedere a: direttorio corrente al CLASSPATH:

• interfacce che definiscono il servizio CLASSPATH=.:$CLASSPATH


• stub delle classi di implementazione del servizio export CLASSPATH
• classi del server usati dal client (es. valori di ritorno)
• altre classi utilizzate dal client E se volessimo lanciare il client, il server, e
l’rmiregistry in direttori diversi?
È necessario:
Si noti che questa è la modalità standard in Linux per
1. localizzare il codice (in locale o in remoto) aggiungere/modificare una variabile di ambiente.
2. effettuare il download (se in remoto) Nelle FAQ del corso, si veda anche il caso della
3. eseguire in modo sicuro il codice scaricato variabile di ambiente PATH

Reti di calcolatori, Java RMI - 29 Reti di calcolatori, Java RMI - 30


Localizzazione del codice Utilizzo del codebase
Sia il cliente sia il servitore devono avere a Il codebase viene usato dal client per scaricare le
disposizione le classi di supporto per la interazione classi necessarie relative al server (interfaccia, stub,
oggetti restituiti come valori di ritorno)
Le informazioni relative a dove reperire il codice delle
classi - se non disponibile localmente - sono
memorizzate sul server e passate al client by need
⇒ server RMI mandato in esecuzione specificando
nell’opzione
java.rmi.server.codebase
l’URL da cui prelevare le classi necessarie.

L’URL può essere:


una directory del file system locale (file://) Il codebase viene usato dal server per scaricare le
l’indirizzo di un server ftp (ftp://) classi necessarie relative al client (oggetti passati
l’indirizzo di un server http (http://) come parametri nelle chiamate)
Il codebase è una proprietà del server che viene
annotata nel reference pubblicato sul registry

Le classi vengono cercate sempre prima nel


CLASSPATH locale, solo in caso di insuccesso
vengono cercate nel codebase

Reti di calcolatori, Java RMI - 31 Reti di calcolatori, Java RMI - 32


CODEBASE ESEMPIO
Client e Server su host diversi e classi scaricabili via
Sia il server che il client devono essere lanciati http:
specificando il codebase che indica dove sono
disponibili le rispettive classi java –Djava.rmi.server.codebase
= http://server_host_name/…/RMIdir/ServerDir
EchoRMIServer
Esempio con client e server sullo stesso host e classi
in direttori diversi: java –Djava.rmi.server.codebase
= http://client_host_name/…/RMIdir/ClientDir
java –Djava.rmi.server.codebase EchoRMIClient server_host_name
= file://c:\…\RMIdir\ServerDir\
EchoRMIServer
server_host client_host
java –Djava.rmi.server.codebase
= file://c:\…\RMIdir\ClientDir\
JVM 1
EchoRMIClient localhost JVM 3
JVM 2
RMIregistry
RMIregistry
RMI
RMIClient
Client
server&client_host RMI
RMIServer
Server

JVM 1 JVM 2 JVM 3 EchoRMIServer_stub


EchoInterface
rmiregistry
rmiregistry RMI
RMIServer
Server RMI
RMIClient
Client
EchoRMIServer_stub Message

Message Web Web


Webserver
EchoRMIServer_stub Webserver
server server
EchoInterface EchoRMIServer_stub

c:\…\ServerDir\ c:\…\ClientDir\

File System

Reti di calcolatori, Java RMI - 33 Reti di calcolatori, Java RMI - 34


Ambienti separati e protetti FILE di POLICY
Ogni JVM definisce ambienti di esecuzione
differenziati e protetti per diverse parti, in particolare Il file di policy a cui il Secutiry Manager fa riferimento
da remoto per il controllo degli accessi contiene le autorizzazioni
Si usano ClassLoader come separatori associati a consentite
SecurityManager per la specifica di protezione Esempio:

Download del codice grant {


Utilizzo di RMIClassLoader permission java.net.SocketPermission
usato dal supporto RMI per caricare le classi "*:1024-65535",
"connect, accept, resolve";

Esecuzione del codice permission java.net.SocketPermission


Utilizzo di RMISecurityManager "*:80", "connect";
Istanziato all’interno dell’applicazione RMI, sia client permission java.io.FilePermission
che server, come controllore degli accessi, per "/home/lfoschini/*", "read";
};
bloccare quelli non autorizzati

if (System.getSecurityManager() == null) Il primo permesso consente al client e al server di


{ System.setSecurityManager( instaurare le connessioni necessarie all’interazione
new RMISecurityManager()); }
remota (host qualunque, porta utente qualunque,
Sia il server che il client devono essere lanciati primitive consentite)
specificando il file con le autorizzazioni che il security
manager deve caricare Il secondo permesso consente di prelevare il codice da
un server http (host qualunque, porta 80, connect)
Esempio
Il terzo permesso consente di accedere in lettura ad un
java -Djava.security.policy = echo.policy qualsiasi direttorio del file system locale che sia sotto-
EchoRMIServer direttorio di “/home/lfoschini” (concessa solo lettura)
java -Djava.security.policy = echo.policy
EchoRMIClient remoteHost

Reti di calcolatori, Java RMI - 35 Reti di calcolatori, Java RMI - 36


Bibliografia
Sito della Sun:
http://java.sun.com/products/jdk/rmi/

W.Grosso, “Java RMI”, Ed. O’Reilly (2002)

E. Pitt, K. McNiff, “java.rmi, The Remote Methode


Invocation Guide”, Ed. Addison Wesley (2001)

R. Öberg, “Mastering RMI, Developing Enterprise


Applications in Java and EJB”, Ed. Wiley (2001)

Reti di calcolatori, Java RMI - 37

You might also like